summaryrefslogtreecommitdiff
path: root/stack/src/icmp.c
blob: 630e70c75e29e5dbffeb707eb67e37c25baff92d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80


#include <rte_icmp.h>
#include <mr_common.h>
#include <sk_device.h>
#include <sk_stack.h>
#include <sk_common.h>
#include <sk_route.h>
#include <sk_ip.h>

static void icmp_echo_request_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
	struct rte_mbuf * mbuf, struct in_addr s_in_addr, struct in_addr d_in_addr)
{
	struct icmp_hdr * icmp_hdr = rte_pktmbuf_mtod(mbuf, struct icmp_hdr *);

	uint32_t cksum;
	icmp_hdr->icmp_type = IP_ICMP_ECHO_REPLY;
	cksum = ~icmp_hdr->icmp_cksum & 0xffff;
	cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
	cksum += htons(IP_ICMP_ECHO_REPLY << 8);
	cksum = (cksum & 0xffff) + (cksum >> 16);
	cksum = (cksum & 0xffff) + (cksum >> 16);
	icmp_hdr->icmp_cksum = cksum;

	struct sk_app_instance * app_instance = dev_desc->app_instance_;
	struct sk_destinfo * destinfo = sk_destinfo_create_by_route(app_instance, s_in_addr);
	if(unlikely(destinfo == NULL))
	{
		sk_packet_free(mbuf, sid, SK_FREE_ICMP_REPLY_NO_DESTINFO);
		return;
	}

	sk_ip_packet_construct(app_instance, mbuf, destinfo, IPPROTO_ICMP);
	sk_device_loop_packet_send(destinfo->d_dev_desc, sid, &mbuf, 1);
	return;
}

int protocol_serv_icmp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
                             struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
{
	int handled_packets = 0;
	struct in_addr s_in_addr;
	struct in_addr d_in_addr;

	for (int i = 0; i < nr_mbufs_in; i++)
	{
		struct rte_mbuf * mbuf = mbufs_in[i];
		if (unlikely(mbuf == NULL)) continue;

		// ������IPv4����
		if (!RTE_ETH_IS_IPV4_HDR(mbuf->packet_type)) continue;
		
		// ��IPv4��������
		struct ipv4_hdr * ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct ipv4_hdr *,
			sizeof(struct ether_hdr));

		if (ip_hdr->next_proto_id != IPPROTO_ICMP) continue;
		
		s_in_addr.s_addr = ip_hdr->src_addr;
		d_in_addr.s_addr = ip_hdr->dst_addr;
		
		rte_pktmbuf_adj(mbuf, sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr));
		struct icmp_hdr * icmp_hdr = rte_pktmbuf_mtod(mbuf, struct icmp_hdr *);

		// ICMP��������
		if (icmp_hdr->icmp_type == IP_ICMP_ECHO_REQUEST)
		{
			icmp_echo_request_entry(dev_desc, sid, mbuf, s_in_addr, d_in_addr);
		}
		else // �������Ͳ�����
		{
			sk_packet_free(mbuf, sid, SK_FREE_ICMP_CANNOT_HANDLE_TYPE);
		}

		mbufs_in[i] = NULL;
		handled_packets++;
	}

	return handled_packets;
}