-
Notifications
You must be signed in to change notification settings - Fork 3
/
pkt_dump.c
172 lines (140 loc) · 4.35 KB
/
pkt_dump.c
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019 Microsoft Corporation
* All rights reserved.
*/
#include <arpa/inet.h> // for inet_ntop
#include <netinet/in.h> // for ntohs, INET6_ADDRSTRLEN, IPPROTO_GRE
#include <rte_arp.h> // for rte_arp_hdr, RTE_ARP_OP_REPLY, RTE_AR...
#include <rte_byteorder.h> // for rte_be_to_cpu_16, rte_be_to_cpu_32
#include <rte_cycles.h>
#include <rte_ether.h> // for rte_ether_hdr, rte_ether_format_addr
#include <rte_gre.h> // for rte_gre_hdr
#include <rte_ip.h> // for rte_ipv6_hdr, rte_ipv4_hdr, RTE_IPV4_...
#include <rte_mbuf.h> // for rte_mbuf, ...
#include <rte_udp.h> // for rte_udp_hdr
#include <rte_vxlan.h> // for rte_vxlan_hdr
#include <stdint.h> // for uint8_t, uint32_t, uint16_t
#include <stdio.h> // for printf, snprintf, size_t
#include <sys/socket.h> // for AF_INET, AF_INET6
#include "pkt_dump.h"
#define VXLAN_PORT 4789
static void pkt_decode(const struct rte_ether_hdr *eh);
static const char *ip_proto(uint16_t proto)
{
static char buf[32];
switch (proto) {
case IPPROTO_ICMP: return "ICMP";
case IPPROTO_TCP: return "TCP";
case IPPROTO_UDP: return "UDP";
case IPPROTO_SCTP: return "SCP";
case IPPROTO_GRE: return "GRE";
default:
snprintf(buf, sizeof(buf), "[%#x]", proto);
return buf;
}
}
static void vxlan_decode(const struct rte_vxlan_hdr *vxlan)
{
uint32_t vni = rte_be_to_cpu_32(vxlan->vx_vni) >> 8;
printf(" VXLAN %u ", vni);
pkt_decode((const struct rte_ether_hdr *)(vxlan + 1));
}
static void gre_decode(const void *p)
{
const struct rte_gre_hdr *gre = p;
if (gre->proto == htons(0x6558)) {
printf(" NVGRE");
} else {
printf(" GRE[%#x]", ntohs(gre->proto));
return;
}
p = gre + 1;
if (gre->c) {
/* decode checksum? */
}
if (gre->k) {
const uint32_t *key = p;
uint32_t id = ntohl(*key);
printf(" %#x:%x ", id >> 8, id & 0xff);
p = key + 1;
}
if (gre->s) {
/* sequence number */
}
pkt_decode(p);
}
static void pkt_decode(const struct rte_ether_hdr *eh)
{
char src_str[INET6_ADDRSTRLEN], dst_str[INET6_ADDRSTRLEN];
rte_ether_format_addr(src_str, sizeof(src_str), &eh->s_addr);
rte_ether_format_addr(dst_str, sizeof(dst_str), &eh->d_addr);
printf("%s → %s ", src_str, dst_str);
switch (rte_be_to_cpu_16(eh->ether_type)) {
case RTE_ETHER_TYPE_IPV4: {
const struct rte_ipv4_hdr *ip
= (const struct rte_ipv4_hdr *)(eh + 1);
size_t hlen;
hlen = (ip->version_ihl & RTE_IPV4_HDR_IHL_MASK)
* RTE_IPV4_IHL_MULTIPLIER;
inet_ntop(AF_INET, &ip->src_addr, src_str, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &ip->dst_addr, dst_str, INET_ADDRSTRLEN);
printf("%s → %s ", src_str, dst_str);
if (ip->next_proto_id == IPPROTO_UDP) {
const struct rte_udp_hdr *udp;
udp = (const struct rte_udp_hdr *)
((const uint8_t *)ip + hlen);
if (ntohs(udp->dst_port) == VXLAN_PORT) {
vxlan_decode((const struct rte_vxlan_hdr *)(udp +1));
return;
}
}
if (ip->next_proto_id == IPPROTO_GRE) {
gre_decode((const uint8_t *)ip + hlen);
return;
}
printf("%s", ip_proto(ip->next_proto_id));
break;
}
case RTE_ETHER_TYPE_IPV6: {
const struct rte_ipv6_hdr *ip6
= (const struct rte_ipv6_hdr *)(eh + 1);
inet_ntop(AF_INET6, &ip6->src_addr, src_str, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &ip6->dst_addr, dst_str, INET6_ADDRSTRLEN);
printf("%s → %s ", src_str, dst_str);
if (ip6->proto == IPPROTO_UDP) {
const struct rte_udp_hdr *udp;
udp = (const struct rte_udp_hdr *)(ip6 + 1);
if (ntohs(udp->dst_port) == VXLAN_PORT) {
vxlan_decode((const struct rte_vxlan_hdr *)(udp +1));
return;
}
}
if (ip6->proto == IPPROTO_GRE) {
gre_decode((const uint8_t *)(ip6 + 1));
return;
}
printf("%s", ip_proto(ip6->proto));
break;
}
case RTE_ETHER_TYPE_ARP: {
const struct rte_arp_hdr *ah
= (const struct rte_arp_hdr *)(eh + 1);
uint16_t op = rte_be_to_cpu_16(ah->arp_opcode);
printf("ARP %s",
op == RTE_ARP_OP_REQUEST ? "REQ" :
op == RTE_ARP_OP_REPLY ? "REPLY" : "???");
break;
}
default:
printf("type %#x", ntohs(eh->ether_type));
}
}
void pkt_print(const struct rte_mbuf *m)
{
const struct rte_ether_hdr *eh;
eh = rte_pktmbuf_mtod(m, const struct rte_ether_hdr *);
if (m->ol_flags & PKT_RX_VLAN_STRIPPED)
printf("{%u} ", m->vlan_tci);
pkt_decode(eh);
printf(" length %u\n", m->pkt_len);
}