Line data Source code
1 : /*
2 : * vr_packet.h -- packet handling functionality of vrouter
3 : *
4 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
5 : * Copyright Contributors to the OpenSDN project
6 : */
7 : #ifndef __VR_PACKET_H__
8 : #define __VR_PACKET_H__
9 :
10 : #include "vr_defs.h"
11 : #include "vr_qos.h"
12 : #include "vr_flow.h"
13 : #include "vrouter.h"
14 : #include "vr_btable.h"
15 : #include "vr_bridge.h"
16 : #include "vr_mirror.h"
17 : #include "vr_os.h"
18 : #include "vr_pkt_droplog.h"
19 : #include "vr_hash.h"
20 :
21 : /* ethernet header */
22 : #define VR_ETHER_DMAC_OFF 0
23 : #define VR_ETHER_SMAC_OFF 6
24 : #define VR_ETHER_PROTO_OFF 12
25 : #define VR_ETHER_VLAN_PROTO_OFF 16
26 :
27 : #define VR_ETHER_PROTO_MAC_OFF 1
28 : #define VR_ETHER_PROTO_MAC_LEN 2
29 :
30 : #define VR_IP_PROTO_ICMP 1
31 : #define VR_IP_PROTO_IGMP 2
32 : #define VR_IP_PROTO_TCP 6
33 : #define VR_IP_PROTO_UDP 17
34 : #define VR_IP_PROTO_GRE 47
35 : #define VR_IP_PROTO_ICMP6 58
36 : #define VR_IP_PROTO_SCTP 132
37 :
38 : #define VR_GRE_FLAG_CSUM (ntohs(0x8000))
39 : #define VR_GRE_FLAG_KEY (ntohs(0x2000))
40 :
41 : #define VR_DHCP_SRC_PORT 68
42 : #define VR_DHCP6_SRC_PORT 546
43 :
44 : #define VR_BFD_SINGLE_HOP_PORT 3784
45 : #define VR_BFD_STATE_FLAG_MASK 0xc0
46 :
47 : /* Size of basic GRE header */
48 : #define VR_GRE_BASIC_HDR_LEN 4
49 :
50 : /* Size of GRE header with checksum */
51 : #define VR_GRE_CKSUM_HDR_LEN 8
52 :
53 : /* Size of GRE header with key */
54 : #define VR_GRE_KEY_HDR_LEN 8
55 :
56 : #define VR_DYNAMIC_PORT_START 0
57 : #define VR_DYNAMIC_PORT_END 65535
58 :
59 : /*
60 : * Overlay length used for TCP MSS adjust. For UDP outer header, overlay
61 : * len is 20 (IP header) + 8 (UDP) + 4 (MPLS). For GRE, it is 20 (IP header)
62 : * + 8 (GRE header + key) + 4 (MPLS). Instead of allowing for only one
63 : * label, we will allow a maximum of 3 labels, so we end up with 40 bytes
64 : * of overleay headers.
65 : */
66 : #define VROUTER_OVERLAY_LEN 40
67 :
68 : /*
69 : * Over lay length is going to be ethernet header bytes more incase of L2 packet
70 : */
71 : #define VROUTER_L2_OVERLAY_LEN 62
72 :
73 :
74 : /* packets originated by DP. For eg: mirrored packets */
75 : #define VP_FLAG_FROM_DP (1 << 0)
76 : #define VP_FLAG_TO_ME (1 << 1)
77 : /* request policy lookup - for components other than interfaces */
78 : #define VP_FLAG_FLOW_GET (1 << 2)
79 : /* packet already went through one round of policy lookup */
80 : #define VP_FLAG_FLOW_SET (1 << 3)
81 : #define VP_FLAG_MULTICAST (1 << 4)
82 : /* Partially checksummed by VM */
83 : #define VP_FLAG_CSUM_PARTIAL (1 << 5)
84 : /* Attempt to do receive offload on inner packet */
85 : #define VP_FLAG_GRO (1 << 6)
86 : /* Attempt to do segmentation on inner packet */
87 : #define VP_FLAG_GSO (1 << 7)
88 : /* Diagnostic packet */
89 : #define VP_FLAG_DIAG (1 << 8)
90 : #define VP_FLAG_GROED (1 << 9)
91 :
92 : /*
93 : * possible 256 values of what a packet can be. currently, this value is
94 : * used only as an aid in fragmentation.
95 : */
96 : #define VP_TYPE_NULL 0
97 :
98 : #define VP_TYPE_ARP 1
99 : #define VP_TYPE_IP 2
100 : #define VP_TYPE_IP6 3
101 :
102 : #define VP_TYPE_IPOIP 4
103 : #define VP_TYPE_IP6OIP 5
104 :
105 : #define VP_TYPE_AGENT 6
106 : #define VP_TYPE_PBB 7
107 : #define VP_TYPE_UNKNOWN 8
108 : #define VP_TYPE_MAX VP_TYPE_UNKNOWN
109 :
110 :
111 : /*
112 : * Values to define how to proceed with handling a packet.
113 : */
114 : #define PKT_RET_FAST_PATH 1
115 : #define PKT_RET_SLOW_PATH 2
116 : #define PKT_RET_ERROR 3
117 : #define PKT_RET_UNHANDLED 4
118 :
119 : /*
120 : * Values to define the MPLS tunnel type
121 : */
122 : #define PKT_MPLS_TUNNEL_INVALID 0x00
123 : #define PKT_MPLS_TUNNEL_L3 0x01
124 : #define PKT_MPLS_TUNNEL_L2_UCAST 0x02
125 : #define PKT_MPLS_TUNNEL_L2_MCAST 0x03
126 : #define PKT_MPLS_TUNNEL_L2_CONTROL_DATA 0x04
127 :
128 :
129 : /*
130 : * Values to defaine the srouce of Multicast packet
131 : */
132 : #define PKT_SRC_TOR_REPL_TREE 0x1
133 : #define PKT_SRC_INGRESS_REPL_TREE 0x2
134 : #define PKT_SRC_EDGE_REPL_TREE 0x4
135 : #define PKT_SRC_ANY_REPL_TREE (PKT_SRC_TOR_REPL_TREE | \
136 : PKT_SRC_SRC_REPL_TREE | PKT_SRC_EDGE_REPL_TREE)
137 :
138 :
139 : /*
140 : * Values to define the encap type of outgoing packet
141 : */
142 : #define PKT_ENCAP_MPLS 0x01
143 : #define PKT_ENCAP_VXLAN 0x02
144 :
145 : /*
146 : * NOTE: Please do not add any more fields without ensuring
147 : * that the size is <= 48 bytes in 64 bit systems.
148 : */
149 : struct vr_packet {
150 : unsigned char *vp_head;
151 : struct vr_interface *vp_if;
152 : struct vr_nexthop *vp_nh;
153 : unsigned short vp_data;
154 : unsigned short vp_tail;
155 : unsigned short vp_len;
156 : unsigned short vp_end;
157 : unsigned short vp_network_h;
158 : unsigned short vp_flags;
159 : unsigned short vp_inner_network_h;
160 : unsigned char vp_cpu;
161 : unsigned char vp_type;
162 : unsigned char vp_ttl;
163 : unsigned char vp_queue;
164 : unsigned char vp_priority:4,
165 : vp_rx_pass:1,
166 : vp_notused:3;
167 : };
168 :
169 :
170 : #define VP_QUEUE_INVALID 0xFF
171 : #define VP_PRIORITY_INVALID 0xF
172 :
173 : extern void pkt_reset(struct vr_packet *);
174 : extern struct vr_packet *pkt_copy(struct vr_packet *, unsigned short,
175 : unsigned short);
176 : extern struct vr_packet *pkt_cow(struct vr_packet *, unsigned short);
177 : extern int vr_myip(struct vr_interface *, unsigned int);
178 : extern unsigned int vr_get_pkt_hash(struct vr_packet *);
179 :
180 : typedef enum {
181 : L4_TYPE_UNKNOWN,
182 : L4_TYPE_DHCP_REQUEST,
183 : L4_TYPE_ROUTER_SOLICITATION,
184 : L4_TYPE_NEIGHBOUR_SOLICITATION,
185 : L4_TYPE_NEIGHBOUR_ADVERTISEMENT,
186 : L4_TYPE_IGMP,
187 : } l4_pkt_type_t;
188 :
189 : __attribute__packed__open__
190 : struct vr_eth {
191 : unsigned char eth_dmac[VR_ETHER_ALEN];
192 : unsigned char eth_smac[VR_ETHER_ALEN];
193 : unsigned short eth_proto;
194 : } __attribute__packed__close__;
195 :
196 : #define VLAN_ID_INVALID 0xFFFF
197 : #define VLAN_ID_MAX 0xFFFF
198 : #define VR_VLAN_PRIORITY_SHIFT 13
199 :
200 : __attribute__packed__open__
201 : struct vr_vlan_hdr {
202 : unsigned short vlan_tag;
203 : unsigned short vlan_proto;
204 : } __attribute__packed__close__;
205 :
206 : __attribute__packed__open__
207 : struct vr_pbb_itag {
208 : uint8_t pbbi_pcp:3,
209 : pbbi_dei:1,
210 : pbbi_uca:1,
211 : pbbi_res:3;
212 : uint32_t pbbi_isid:24;
213 : } __attribute__packed__close__;
214 :
215 : __attribute__packed__open__
216 : struct vr_eth_hbs_md {
217 : unsigned short magic_dmac;
218 : unsigned int flow_id_dmac;
219 : unsigned short magic_smac;
220 : unsigned int flow_id_smac;
221 : unsigned short eth_proto;
222 : } __attribute__packed__close__;
223 :
224 : #define VR_ARP_HW_LEN 6
225 : #define VR_ARP_OP_REQUEST 1
226 : #define VR_ARP_OP_REPLY 2
227 :
228 : #define VR_ETH_PROTO_ARP 0x806
229 : #define VR_ETH_PROTO_IP 0x800
230 : #define VR_ETH_PROTO_IP6 0x86DD
231 : #define VR_ETH_PROTO_VLAN 0x8100
232 : #define VR_ETH_PROTO_PBB 0x88E7
233 :
234 : #define VR_DIAG_CSUM 0xffff
235 : #define VR_UDP_PORT_RANGE_START 49152
236 : #define VR_UDP_PORT_RANGE_END 65535
237 :
238 : #define VR_INVALID_MTU 0xFFFF
239 :
240 : static inline int8_t
241 4 : vr_vlan_get_tos(uint8_t *eth_data)
242 : {
243 4 : struct vr_eth *eth = (struct vr_eth *)eth_data;
244 : struct vr_vlan_hdr *vlan;
245 :
246 4 : if (ntohs(eth->eth_proto) != VR_ETH_PROTO_VLAN)
247 4 : return -1;
248 :
249 0 : vlan = (struct vr_vlan_hdr *)(eth + 1);
250 0 : return (ntohs(vlan->vlan_tag) >> VR_VLAN_PRIORITY_SHIFT);
251 : }
252 :
253 : #ifdef arp_op
254 : #undef arp_op
255 : #endif
256 :
257 : #define VR_ARP_HW_TYPE_ETHER 1
258 : #define VR_ARP_PROTO_LEN_IPV4 4
259 :
260 : __attribute__packed__open__
261 : struct vr_arp {
262 : unsigned short arp_hw;
263 : unsigned short arp_proto;
264 : unsigned char arp_hwlen;
265 : unsigned char arp_protolen;
266 : unsigned short arp_op;
267 : unsigned char arp_sha[VR_ARP_HW_LEN];
268 : unsigned int arp_spa;
269 : unsigned char arp_dha[VR_ARP_HW_LEN];
270 : unsigned int arp_dpa;
271 : } __attribute__packed__close__;
272 :
273 : static inline bool
274 12 : vr_grat_arp(struct vr_arp *sarp)
275 : {
276 : /*
277 : * Treat below two as Gratuitous ARP
278 : * Null source IP - ARP Probe
279 : * Source IP same as dest IP - ARP Announcement
280 : */
281 12 : if ((!sarp->arp_spa) || (sarp->arp_spa == sarp->arp_dpa))
282 0 : return true;
283 12 : return false;
284 : }
285 :
286 : #define VR_IP_DF (0x1 << 14)
287 : #define VR_IP_MF (0x1 << 13)
288 : #define VR_IP_FRAG_OFFSET_MASK (VR_IP_MF - 1)
289 : #define VR_IP_DSCP(val) ((val) << 2)
290 :
291 : #define VR_IP_ADDRESS_LEN 4
292 :
293 : #define VR_IP6_MF 0x1
294 : #define VR_IP6_FRAG_OFFSET_BITS 3
295 :
296 : __attribute__packed__open__
297 : struct vr_ip {
298 : #if defined(__KERNEL__) && defined(__linux__)
299 : #if defined(__LITTLE_ENDIAN_BITFIELD)
300 : unsigned char ip_hl:4,
301 : ip_version:4;
302 : #elif defined(__BIG_ENDIAN_BITFIELD)
303 : unsigned char ip_version:4,
304 : ip_hl:4;
305 : #endif
306 : #else
307 : #if (__BYTE_ORDER == __LITTLE_ENDIAN)
308 : unsigned char ip_hl:4,
309 : ip_version:4;
310 : #elif (__BYTE_ORDER == __BIG_ENDIAN)
311 : unsigned char ip_version:4,
312 : ip_hl:4;
313 : #endif
314 : #endif
315 : unsigned char ip_tos;
316 : unsigned short ip_len;
317 : unsigned short ip_id;
318 : unsigned short ip_frag_off;
319 : unsigned char ip_ttl;
320 : unsigned char ip_proto;
321 : unsigned short ip_csum;
322 : unsigned int ip_saddr;
323 : unsigned int ip_daddr;
324 : } __attribute__packed__close__;
325 :
326 : static inline void
327 58 : vr_incremental_diff(unsigned int oldval, unsigned int newval,
328 : unsigned int *diff)
329 : {
330 : unsigned int tmp;
331 :
332 58 : tmp = ~oldval + newval;
333 58 : if (tmp < newval)
334 5 : tmp += 1;
335 :
336 58 : *diff += tmp;
337 58 : if (*diff < tmp)
338 6 : *diff += 1;
339 :
340 58 : return;
341 : }
342 :
343 : static inline void
344 48 : vr_ip_incremental_csum(struct vr_ip *ip, unsigned int diff)
345 : {
346 : unsigned int csum;
347 :
348 48 : diff = (diff >> 16) + (diff & 0xffff);
349 48 : if (diff >> 16) {
350 46 : diff &= 0xffff;
351 46 : diff += 1;
352 : }
353 :
354 48 : csum = ~(ip->ip_csum) & 0xffff;
355 48 : csum += diff;
356 48 : csum = (csum >> 16) + (csum & 0xffff);
357 48 : if (csum >> 16)
358 0 : csum = (csum & 0xffff) + 1;
359 :
360 48 : ip->ip_csum = (~csum & 0xffff);
361 48 : return;
362 : }
363 :
364 : static inline uint8_t
365 106 : vr_inet_get_tos(struct vr_ip *iph)
366 : {
367 106 : return (iph->ip_tos & 0xFC) >> 2;
368 : }
369 :
370 : static inline void
371 0 : vr_inet_set_tos(struct vr_ip *iph, uint8_t tos)
372 : {
373 0 : unsigned int diff = 0;
374 :
375 0 : if (iph->ip_tos == tos)
376 0 : return;
377 :
378 0 : vr_incremental_diff(iph->ip_tos << 8, tos << 8, &diff);
379 0 : iph->ip_tos = tos;
380 0 : vr_ip_incremental_csum(iph, diff);
381 :
382 0 : return;
383 : }
384 :
385 :
386 : #define SOURCE_LINK_LAYER_ADDRESS_OPTION 1
387 : #define TARGET_LINK_LAYER_ADDRESS_OPTION 2
388 :
389 : __attribute__packed__open__
390 : struct vr_neighbor_option {
391 : uint8_t vno_type;
392 : uint8_t vno_length;
393 : uint8_t vno_value[];
394 : } __attribute__packed__close__;
395 :
396 : __attribute__packed__open__
397 : struct vr_ip6_frag {
398 : uint8_t ip6_frag_nxt;
399 : uint8_t ip6_frag_res;
400 : uint16_t ip6_frag_offset;
401 : uint32_t ip6_frag_id;
402 : } __attribute__packed__close__;
403 :
404 : __attribute__packed__open__
405 : struct vr_ip6_pseudo {
406 : unsigned char ip6_src[VR_IP6_ADDRESS_LEN];
407 : unsigned char ip6_dst[VR_IP6_ADDRESS_LEN];
408 : unsigned short ip6_l4_length;
409 : unsigned short ip6_zero;
410 : unsigned int ip6_zero_nh;
411 : } __attribute__packed__close__;
412 :
413 :
414 : __attribute__packed__open__
415 : struct vr_ip6 {
416 : #ifdef __KERNEL__
417 : #if defined(__LITTLE_ENDIAN_BITFIELD)
418 : uint8_t ip6_priority_h:4,
419 : ip6_version:4;
420 : uint8_t ip6_flow_h:4,
421 : ip6_priority_l:4;
422 : #elif defined(__BIG_ENDIAN_BITFIELD)
423 : uint8_t ip6_version:4,
424 : ip6_priority_h:4;
425 : uint8_t ip6_priority_l:4,
426 : ip6_flow_h:4;
427 : #endif
428 : #else
429 : #if (__BYTE_ORDER == __LITTLE_ENDIAN)
430 : uint8_t ip6_priority_h:4,
431 : ip6_version:4;
432 : uint8_t ip6_flow_h:4,
433 : ip6_priority_l:4;
434 : #elif (__BYTE_ORDER == __BIG_ENDIAN)
435 : uint8_t ip6_version:4,
436 : ip6_priority_h:4;
437 : uint8_t ip6_priority_l:4,
438 : ip6_flow_h:4;
439 : #endif
440 : #endif
441 : uint16_t ip6_flow_l;
442 : uint16_t ip6_plen;
443 : uint8_t ip6_nxt;
444 : uint8_t ip6_hlim;
445 : uint8_t ip6_src[VR_IP6_ADDRESS_LEN];
446 : uint8_t ip6_dst[VR_IP6_ADDRESS_LEN];
447 : } __attribute__packed__close__;
448 :
449 : #define VR_IP4_MAPPED_IP6_ZERO_BYTES 10
450 : #define VR_IP4_MAPPED_IP6_ONE_BYTES 2
451 :
452 : static inline uint8_t
453 9 : vr_inet6_get_tos(struct vr_ip6 *ip6h)
454 : {
455 9 : return ((((ip6h->ip6_priority_h << 4) | (ip6h->ip6_priority_l)) >> 2) & 0x3F);
456 : }
457 :
458 : static inline void
459 0 : vr_inet6_set_tos(struct vr_ip6 *ip6h, uint8_t tos)
460 : {
461 0 : ip6h->ip6_priority_h = ((tos << 2) >> 4);
462 0 : ip6h->ip6_priority_l = ((tos << 2) & 0xF);
463 :
464 0 : return;
465 : }
466 :
467 : static inline void
468 : vr_inet6_generate_ip6(uint8_t *ip6, uint32_t ip)
469 : {
470 : memset(ip6, 0, VR_IP4_MAPPED_IP6_ZERO_BYTES);
471 : memset(ip6 + VR_IP4_MAPPED_IP6_ZERO_BYTES, 1,
472 : VR_IP4_MAPPED_IP6_ONE_BYTES);
473 : memcpy(ip6 + VR_IP4_MAPPED_IP6_ZERO_BYTES + VR_IP4_MAPPED_IP6_ONE_BYTES,
474 : &ip, sizeof(ip));
475 :
476 : return;
477 : }
478 :
479 : struct tcphdr;
480 :
481 : bool vr_ip_proto_pull(struct vr_ip *);
482 : bool vr_ip6_proto_pull(struct vr_ip6 *);
483 :
484 : int vr_ip_transport_parse(struct vr_ip *iph, struct vr_ip6 *ip6h,
485 : void **thp, unsigned int frag_size,
486 : void (do_tcp_mss_adj)(struct tcphdr *, unsigned short, unsigned char),
487 : unsigned int *hlenp, unsigned short *th_csump, unsigned int *tcph_pull_lenp,
488 : unsigned int *pull_lenp);
489 : int vr_inner_pkt_parse(unsigned char *va,
490 : int (*tunnel_type_cb)(unsigned int, unsigned int, unsigned short *),
491 : int *encap_type, int *pkt_typep, unsigned int *pull_lenp,
492 : unsigned int frag_size, struct vr_ip **iphp, struct vr_ip6 **ip6hp,
493 : unsigned short gre_udp_encap, unsigned char ip_proto);
494 :
495 : #define MCAST_IP (0xE0000000)
496 : #define MCAST_IP_MASK (0xF0000000)
497 : #define IS_BMCAST_IP(ip) \
498 : (((ntohl(ip) & MCAST_IP_MASK) == MCAST_IP) || (ip == 0xFFFFFFFF))
499 :
500 : static inline void
501 0 : vr_mcast_mac_from_isid(uint32_t isid, uint8_t *mac)
502 : {
503 0 : if (!mac)
504 0 : return;
505 :
506 0 : mac[0] = 1;
507 0 : mac[1] = 0x1E;
508 0 : mac[2] = 0x83;
509 0 : mac[3] = 0xFF & (isid >> 16);
510 0 : mac[4] = 0xFF & (isid >> 8);
511 0 : mac[5] = 0xFF & isid;
512 :
513 0 : return;
514 : }
515 :
516 : #define VR_IP_ADDR_SIZE(type) \
517 : ((type == VP_TYPE_IP6) ? VR_IP6_ADDRESS_LEN \
518 : : VR_IP_ADDRESS_LEN)
519 :
520 : static inline unsigned char
521 161 : vr_eth_proto_to_pkt_type(unsigned short eth_proto)
522 : {
523 161 : if (eth_proto == VR_ETH_PROTO_IP)
524 126 : return VP_TYPE_IP;
525 35 : else if (eth_proto == VR_ETH_PROTO_IP6)
526 24 : return VP_TYPE_IP6;
527 11 : else if (eth_proto == VR_ETH_PROTO_ARP)
528 11 : return VP_TYPE_ARP;
529 0 : else if (eth_proto == VR_ETH_PROTO_PBB)
530 0 : return VP_TYPE_PBB;
531 :
532 0 : return VP_TYPE_UNKNOWN;
533 : }
534 :
535 : static inline bool
536 703 : vr_ip_is_ip4(struct vr_ip *iph)
537 : {
538 703 : if ((iph->ip_version & 0xf) == 0x4)
539 694 : return true;
540 9 : return false;
541 : }
542 :
543 : static inline bool
544 177 : vr_ip_is_ip6(struct vr_ip *iph)
545 : {
546 177 : if ((iph->ip_version & 0xf) == 0x6)
547 9 : return true;
548 168 : return false;
549 : }
550 : static inline unsigned char *pkt_network_header(struct vr_packet *);
551 :
552 : static inline bool
553 1 : vr_ip_dont_fragment_set(struct vr_packet *pkt)
554 : {
555 : struct vr_ip *ip;
556 :
557 1 : ip = (struct vr_ip *)pkt_network_header(pkt);
558 1 : if (vr_ip_is_ip6(ip))
559 0 : return true;
560 :
561 1 : if (ntohs(ip->ip_frag_off) & VR_IP_DF)
562 0 : return true;
563 :
564 1 : return false;
565 : }
566 :
567 : static inline bool
568 20 : vr_ip_fragment_tail(struct vr_ip *iph)
569 : {
570 20 : unsigned short frag = ntohs(iph->ip_frag_off);
571 20 : bool more = (frag & VR_IP_MF) ? true : false;
572 20 : unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
573 :
574 20 : if (!vr_ip_is_ip4(iph))
575 0 : return false;
576 :
577 20 : if (!more && offset)
578 5 : return true;
579 :
580 15 : return false;
581 : }
582 :
583 : static inline bool
584 0 : vr_pkt_is_ip(struct vr_packet *pkt)
585 : {
586 0 : if (pkt->vp_type == VP_TYPE_IPOIP || pkt->vp_type == VP_TYPE_IP ||
587 0 : pkt->vp_type == VP_TYPE_IP6OIP)
588 0 : return true;
589 :
590 0 : return false;
591 : }
592 :
593 : static inline bool
594 384 : vr_pkt_type_is_overlay(unsigned short type)
595 : {
596 384 : if (type == VP_TYPE_IPOIP || type == VP_TYPE_IP6OIP)
597 189 : return true;
598 :
599 195 : return false;
600 : }
601 :
602 : static inline bool
603 : vr_pkt_needs_csum_gso_update(struct vr_packet *pkt)
604 : {
605 : if (pkt->vp_flags & VP_FLAG_FROM_DP) {
606 : if (pkt->vp_flags & (VP_FLAG_CSUM_PARTIAL | VP_FLAG_GSO))
607 : return true;
608 : }
609 :
610 : return false;
611 : }
612 :
613 : static inline bool
614 132 : vr_pkt_is_diag(struct vr_packet *pkt)
615 : {
616 132 : if (pkt->vp_flags & VP_FLAG_DIAG)
617 0 : return true;
618 132 : return false;
619 : }
620 :
621 : static inline void
622 : vr_pkt_set_diag(struct vr_packet *pkt)
623 : {
624 : pkt->vp_flags |= VP_FLAG_DIAG;
625 : return;
626 : }
627 :
628 : static inline bool
629 104 : vr_pkt_is_gro(struct vr_packet *pkt)
630 : {
631 104 : if (pkt->vp_flags & VP_FLAG_GRO)
632 4 : return true;
633 100 : return false;
634 : }
635 :
636 : static inline void
637 8 : vr_pkt_set_gro(struct vr_packet *pkt)
638 : {
639 8 : pkt->vp_flags |= VP_FLAG_GRO;
640 8 : return;
641 : }
642 :
643 : static inline void
644 60 : vr_pkt_unset_gro(struct vr_packet *pkt)
645 : {
646 60 : pkt->vp_flags &= ~VP_FLAG_GRO;
647 60 : return;
648 : }
649 :
650 : static inline bool
651 114 : vr_ip_fragment_head(struct vr_ip *iph)
652 : {
653 114 : unsigned short frag = ntohs(iph->ip_frag_off);
654 114 : bool more = (frag & VR_IP_MF) ? true : false;
655 114 : unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
656 :
657 114 : if (!vr_ip_is_ip4(iph))
658 0 : return false;
659 :
660 114 : if (more && !offset)
661 12 : return true;
662 :
663 102 : return false;
664 : }
665 :
666 : static inline bool
667 136 : vr_ip_fragment(struct vr_ip *iph)
668 : {
669 136 : unsigned short frag = ntohs(iph->ip_frag_off);
670 136 : bool more = (frag & VR_IP_MF) ? true : false;
671 136 : unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
672 :
673 136 : if (!vr_ip_is_ip4(iph))
674 1 : return false;
675 :
676 135 : if (offset || more)
677 43 : return true;
678 :
679 92 : return false;
680 : }
681 :
682 : static inline bool
683 201 : vr_ip_transport_header_valid(struct vr_ip *iph)
684 : {
685 201 : unsigned short frag = ntohs(iph->ip_frag_off);
686 201 : unsigned short offset = frag & VR_IP_FRAG_OFFSET_MASK;
687 :
688 201 : if (!vr_ip_is_ip4(iph))
689 0 : return true;
690 :
691 201 : if (offset)
692 64 : return false;
693 :
694 137 : return true;
695 : }
696 :
697 :
698 : #define VR_TCP_FLAG_FIN 0x0001
699 : #define VR_TCP_FLAG_SYN 0x0002
700 : #define VR_TCP_FLAG_RST 0x0004
701 : #define VR_TCP_FLAG_PSH 0x0008
702 : #define VR_TCP_FLAG_ACK 0x0010
703 : #define VR_TCP_FLAG_URG 0x0020
704 : #define VR_TCP_FLAG_ECN 0x0040
705 : #define VR_TCP_FLAG_CWR 0x0080
706 :
707 : #define VR_TCP_OPT_EOL 0
708 : #define VR_TCP_OPT_NOP 1
709 : #define VR_TCP_OPT_MSS 2
710 :
711 : #define VR_TCP_OLEN_MSS 4
712 :
713 : #define VR_TCP_OFFSET(field) ((ntohs(field) & 0xF000) >> 12)
714 : #define VR_TCP_FLAGS(field) (ntohs(field) & 0x01FF)
715 :
716 : __attribute__packed__open__
717 : struct vr_tcp {
718 : unsigned short tcp_sport;
719 : unsigned short tcp_dport;
720 : unsigned int tcp_seq;
721 : unsigned int tcp_ack;
722 : union {
723 : uint16_t tcp_offset_r_flags;
724 : struct {
725 : uint16_t
726 : tcp_res1:4,
727 : tcp_doff:4,
728 : tcp_flag_fin:1,
729 : tcp_flag_syn:1,
730 : tcp_flag_rst:1,
731 : tcp_flag_psh:1,
732 : tcp_flag_ack:1,
733 : tcp_flag_urg:1,
734 : tcp_flag_ece:1,
735 : tcp_flag_cwr:1;
736 : };
737 : };
738 : unsigned short tcp_win;
739 : unsigned short tcp_csum;
740 : unsigned short tcp_urg;
741 : } __attribute__packed__close__;
742 :
743 : __attribute__packed__open__
744 : struct vr_udp {
745 : unsigned short udp_sport;
746 : unsigned short udp_dport;
747 : unsigned short udp_length;
748 : unsigned short udp_csum;
749 : } __attribute__packed__close__;
750 :
751 : __attribute__packed__open__
752 : struct vr_sctp {
753 : unsigned short sctp_sport;
754 : unsigned short sctp_dport;
755 : unsigned int sctp_vtag;
756 : unsigned int sctp_csum;
757 : } __attribute__packed__close__;
758 :
759 : bool vr_adjust_tcp_mss(struct vr_tcp *tcph, uint16_t len_overhead, uint16_t *old_mss, uint16_t *new_mss);
760 :
761 : bool __vr_adjust_tcp_mss(struct vr_tcp *tcph, uint16_t len_overhead, uint16_t eth_mtu, uint16_t *old_mss, uint16_t *new_mss);
762 :
763 : #define VR_ICMP_TYPE_ECHO_REPLY 0
764 : #define VR_ICMP_TYPE_DEST_UNREACH 3
765 : #define VR_ICMP_TYPE_ECHO 8
766 : #define VR_ICMP_TYPE_TIME_EXCEEDED 11
767 :
768 : #define VR_ICMP6_TYPE_PKT_TOO_BIG 2
769 : #define VR_ICMP6_TYPE_ECHO_REQ 128
770 : #define VR_ICMP6_TYPE_ECHO_REPLY 129
771 : #define VR_ICMP6_TYPE_ROUTER_SOL 133
772 : #define VR_ICMP6_TYPE_ROUTER_AD 134
773 : #define VR_ICMP6_TYPE_NEIGH_SOL 135
774 : #define VR_ICMP6_TYPE_NEIGH_AD 136
775 : #define VR_ICMP6_TYPE_REDIRECT 137
776 :
777 : #define VR_ICMP6_NEIGH_AD_FLAG_ROUTER 0x8000
778 : #define VR_ICMP6_NEIGH_AD_FLAG_SOLCITED 0x4000
779 : #define VR_ICMP6_NEIGH_AD_FLAG_OVERRIDE 0x2000
780 :
781 : #define VR_ICMP6_NEIGH_AD_FLAG_ROUTER 0x8000
782 : #define VR_ICMP6_NEIGH_AD_FLAG_SOLCITED 0x4000
783 : #define VR_ICMP6_NEIGH_AD_FLAG_OVERRIDE 0x2000
784 :
785 : #define VR_IP6_PROTO_FRAG 44
786 :
787 : __attribute__packed__open__
788 : struct vr_icmp {
789 : uint8_t icmp_type;
790 : uint8_t icmp_code;
791 : uint16_t icmp_csum;
792 : /* now only for icmp echo */
793 : uint16_t icmp_eid;
794 : uint16_t icmp_eseq;
795 : uint8_t icmp_data[]; /* compatibility with ICMPv6 */
796 : } __attribute__packed__close__;
797 :
798 : static inline bool
799 33 : vr_icmp_echo(struct vr_icmp *icmph)
800 : {
801 33 : uint8_t type = icmph->icmp_type;
802 :
803 33 : if ((type == VR_ICMP_TYPE_ECHO) ||
804 : (type == VR_ICMP_TYPE_ECHO_REPLY))
805 33 : return true;
806 :
807 0 : return false;
808 : }
809 :
810 : static inline bool
811 0 : vr_v6_prefix_is_ll(uint8_t *prefix)
812 : {
813 0 : if (prefix && (prefix[0] == 0xFE) && (prefix[1] == 0x80))
814 0 : return true;
815 :
816 0 : return false;
817 : }
818 :
819 : static inline bool
820 2 : vr_v6_prefix_null(uint8_t *prefix)
821 : {
822 2 : uint64_t *p = (uint64_t *)(prefix);
823 2 : if (p && (!p[0]) && (!p[1]))
824 0 : return true;
825 :
826 2 : return false;
827 : }
828 :
829 : static inline bool
830 38 : vr_icmp_error(struct vr_icmp *icmph)
831 : {
832 38 : uint8_t type = icmph->icmp_type;
833 :
834 38 : if ((type == VR_ICMP_TYPE_DEST_UNREACH) ||
835 : (type == VR_ICMP_TYPE_TIME_EXCEEDED))
836 1 : return true;
837 :
838 37 : return false;
839 : }
840 :
841 : static inline bool
842 14 : vr_ip6_transport_header_valid(struct vr_ip6 *ip6)
843 : {
844 : struct vr_ip6_frag *frag;
845 : unsigned short offset;
846 :
847 14 : if (ip6->ip6_nxt != VR_IP6_PROTO_FRAG)
848 14 : return true;
849 :
850 0 : frag = (struct vr_ip6_frag *)(ip6 + 1);
851 0 : offset = (ntohs(frag->ip6_frag_offset)) >> VR_IP6_FRAG_OFFSET_BITS;
852 0 : if (offset)
853 0 : return false;
854 :
855 0 : return true;
856 : }
857 :
858 : static inline bool
859 1 : vr_ip6_fragment(struct vr_ip6 *ip6)
860 : {
861 1 : if (ip6->ip6_nxt == VR_IP6_PROTO_FRAG)
862 0 : return true;
863 :
864 1 : return false;
865 : }
866 :
867 : static inline bool
868 4 : vr_ip6_fragment_head(struct vr_ip6 *ip6)
869 : {
870 : struct vr_ip6_frag *frag;
871 : unsigned short offset;
872 : bool more;
873 :
874 4 : if (ip6->ip6_nxt != VR_IP6_PROTO_FRAG)
875 4 : return false;
876 :
877 0 : frag = (struct vr_ip6_frag *)(ip6 + 1);
878 0 : offset = ntohs(frag->ip6_frag_offset);
879 0 : more = (offset & VR_IP6_MF) ? true : false;
880 0 : offset = offset >> VR_IP6_FRAG_OFFSET_BITS;
881 :
882 0 : if (more && !offset)
883 0 : return true;
884 :
885 0 : return false;
886 : }
887 :
888 :
889 : static inline bool
890 2 : vr_icmp6_error(struct vr_icmp *icmp6)
891 : {
892 2 : uint8_t type = icmp6->icmp_type;
893 :
894 2 : if (type < 128)
895 0 : return true;
896 :
897 2 : return false;
898 : }
899 :
900 : __attribute__packed__open__
901 : struct vr_gre {
902 : unsigned short gre_flags;
903 : unsigned short gre_proto;
904 : } __attribute__packed__close__;
905 :
906 : __attribute__packed__open__
907 : struct vr_gre_key {
908 : struct vr_gre gre_comm_hdr;
909 : unsigned int gre_key;
910 : } __attribute__packed__close__;
911 :
912 : struct vr_pcap {
913 : /* timestamp seconds */
914 : unsigned int pcap_ts_sec;
915 : /* timestamp microseconds */
916 : unsigned int pcap_ts_usec;
917 : /* number of octets of packet saved in file */
918 : unsigned int pcap_incl_len;
919 : /* actual length of packet */
920 : unsigned int pcap_orig_len;
921 : };
922 :
923 : __attribute__packed__open__
924 : struct vr_vxlan {
925 : unsigned int vxlan_flags;
926 : unsigned int vxlan_vnid;
927 : } __attribute__packed__close__;
928 :
929 : #define VR_VXLAN_IBIT 0x08000000
930 : #define VR_VXLAN_RABIT 0x01000000
931 :
932 : /*
933 : * Mcast packet adds the following before replicating
934 : * Original Transport + IP Header
935 : * New Mpls header (4 bytes)
936 : * New Udp header (It could be GRE Mpls or Udp Mpls tunnel. Wee need to
937 : * take the maximum of two )
938 : * New IP header
939 : * New L2 header (eth + vlan)
940 : */
941 : #define VR_L3_MCAST_PKT_HEAD_SPACE (sizeof(struct vr_eth) + \
942 : sizeof(struct vr_vlan_hdr) + \
943 : sizeof(struct vr_ip) + \
944 : sizeof(struct vr_udp) + 4)
945 :
946 : /*
947 : * The complete VXlan header contains IP and UDP header
948 : */
949 : #define VR_VXLAN_HDR_LEN (sizeof(struct vr_vxlan) + \
950 : sizeof(struct vr_ip) + sizeof(struct vr_udp))
951 :
952 : #define VR_VXLAN_PKT_LEN (sizeof(struct vr_eth) + \
953 : sizeof(struct vr_ip) + \
954 : sizeof(struct vr_udp) + \
955 : sizeof(struct vr_vxlan))
956 :
957 : #define VR_L2_CTRL_DATA (0x0000)
958 : #define VR_L2_CTRL_DATA_LEN 4
959 :
960 : /*
961 : * The L2 mcast head space contains Vxlan header and 4 bytes of control
962 : * word inaddtion to L3 mcast head space
963 : */
964 : #define VR_L2_MCAST_PKT_HEAD_SPACE (VR_L3_MCAST_PKT_HEAD_SPACE + \
965 : VR_VXLAN_HDR_LEN + \
966 : VR_L2_CTRL_DATA_LEN)
967 :
968 :
969 : extern unsigned short vr_ip_csum(struct vr_ip *);
970 : extern unsigned short vr_generate_unique_ip_id(void);
971 : extern void vr_proto_fragment(struct vr_interface *, struct vr_packet *);
972 : extern unsigned short vr_ip_partial_csum(struct vr_ip *);
973 : extern unsigned short vr_ip6_partial_csum(struct vr_ip6 *);
974 :
975 : enum {
976 : UNKNOWN_SOURCE,
977 : TOR_SOURCE,
978 : TOR_EVPN_SOURCE,
979 : };
980 :
981 : enum {
982 : VR_LABEL_TYPE_UNKNOWN,
983 : VR_LABEL_TYPE_MPLS,
984 : VR_LABEL_TYPE_VXLAN_ID
985 : };
986 :
987 : /*
988 : * forwarding metadata is something that is carried through out the
989 : * forwarding path. we are constrained by what can be held in the
990 : * packet, and hence this structure should be of great use. mostly
991 : * a local variable (in stack), this should not cause performance
992 : * degradation, if so used. please also watch what you are doing with
993 : * this variable
994 : */
995 : #define FMD_FLAG_LABEL_IS_VXLAN_ID 0x01
996 : #define FMD_FLAG_MAC_IS_MY_MAC 0x02
997 : #define FMD_FLAG_ETREE_ENABLE 0x04
998 : #define FMD_FLAG_ETREE_ROOT 0x08
999 : #define FMD_FLAG_L2_CONTROL_DATA 0x10
1000 :
1001 : /*
1002 : * 16 bits of fmd_mirror_data constitutes the below
1003 : * MSB - 0 - last 12 bits indicate Vlan id
1004 : * MSB - 1 - Last 13 bits are interface id
1005 : * 2 bits after MSB - Mirror type
1006 : */
1007 :
1008 : #define FMD_MIRROR_INVALID_DATA 0xFFFF
1009 :
1010 : /* We don't expect packet to loop through the same set
1011 : * of functions more than twice. To be conservative,
1012 : * make it value as 4
1013 : */
1014 : #define FMD_PKT_LOOP_TTL 4
1015 :
1016 : struct vr_forwarding_md {
1017 : struct vr_flow_entry *fmd_fe;
1018 : int32_t fmd_flow_index;
1019 : int32_t fmd_label;
1020 : int8_t fmd_ecmp_nh_index;
1021 : int8_t fmd_ecmp_src_nh_index;
1022 : int16_t fmd_dvrf;
1023 : uint32_t fmd_outer_src_ip;
1024 : uint16_t fmd_vlan;
1025 : uint16_t fmd_mirror_data;
1026 : uint16_t fmd_udp_src_port;
1027 : uint8_t fmd_to_me;
1028 : uint8_t fmd_src;
1029 : uint8_t fmd_flags;
1030 : int8_t fmd_dscp;
1031 : int8_t fmd_dotonep;
1032 : int8_t fmd_dmac[VR_ETHER_ALEN];
1033 : int8_t fmd_smac[VR_ETHER_ALEN];
1034 : int8_t fmd_local_ttl;
1035 : int8_t fmd_underlay_ecmp_index;
1036 : };
1037 :
1038 : static inline void
1039 510 : vr_init_forwarding_md(struct vr_forwarding_md *fmd)
1040 : {
1041 510 : fmd->fmd_fe = NULL;
1042 510 : fmd->fmd_flow_index = -1;
1043 510 : fmd->fmd_ecmp_nh_index = -1;
1044 510 : fmd->fmd_ecmp_src_nh_index = -1;
1045 510 : fmd->fmd_label = -1;
1046 510 : fmd->fmd_dvrf = -1;
1047 510 : fmd->fmd_outer_src_ip = 0;
1048 510 : fmd->fmd_vlan = VLAN_ID_INVALID;
1049 510 : fmd->fmd_mirror_data = FMD_MIRROR_INVALID_DATA;
1050 510 : fmd->fmd_udp_src_port = 0;
1051 510 : fmd->fmd_to_me = 0;
1052 510 : fmd->fmd_src = 0;
1053 510 : fmd->fmd_flags = 0;
1054 510 : fmd->fmd_dscp = -1;
1055 510 : fmd->fmd_dotonep = -1;
1056 510 : fmd->fmd_local_ttl = FMD_PKT_LOOP_TTL;
1057 510 : fmd->fmd_underlay_ecmp_index = -1;
1058 510 : VR_MAC_RESET(fmd->fmd_dmac);
1059 510 : VR_MAC_RESET(fmd->fmd_smac);
1060 :
1061 510 : return;
1062 : }
1063 :
1064 : static inline bool
1065 29 : vr_fmd_label_is_vxlan_id(struct vr_forwarding_md *fmd)
1066 : {
1067 29 : if (fmd->fmd_flags & FMD_FLAG_LABEL_IS_VXLAN_ID)
1068 0 : return true;
1069 29 : return false;
1070 : }
1071 :
1072 : static inline void
1073 0 : vr_fmd_update_etree(struct vr_forwarding_md *fmd, bool valid)
1074 : {
1075 0 : if (valid)
1076 0 : fmd->fmd_flags |= FMD_FLAG_ETREE_ENABLE;
1077 : else
1078 0 : fmd->fmd_flags &= ~FMD_FLAG_ETREE_ENABLE;
1079 :
1080 0 : return;
1081 : }
1082 :
1083 : static inline void
1084 55 : vr_fmd_update_etree_root(struct vr_forwarding_md *fmd, bool root)
1085 : {
1086 55 : if (root)
1087 35 : fmd->fmd_flags |= FMD_FLAG_ETREE_ROOT;
1088 : else
1089 20 : fmd->fmd_flags &= ~FMD_FLAG_ETREE_ROOT;
1090 :
1091 55 : return;
1092 : }
1093 :
1094 : static inline bool
1095 14 : vr_fmd_etree_is_enabled(struct vr_forwarding_md *fmd)
1096 : {
1097 14 : if (fmd->fmd_flags & FMD_FLAG_ETREE_ENABLE)
1098 0 : return true;
1099 :
1100 14 : return false;
1101 : }
1102 :
1103 : static inline bool
1104 0 : vr_fmd_etree_is_root(struct vr_forwarding_md *fmd)
1105 : {
1106 0 : if (fmd->fmd_flags & FMD_FLAG_ETREE_ROOT)
1107 0 : return true;
1108 :
1109 0 : return false;
1110 : }
1111 :
1112 : static inline void
1113 192 : vr_fmd_update_label_type(struct vr_forwarding_md *fmd,
1114 : unsigned int type)
1115 : {
1116 192 : if (type == VR_LABEL_TYPE_VXLAN_ID) {
1117 9 : fmd->fmd_flags |= FMD_FLAG_LABEL_IS_VXLAN_ID;
1118 : } else {
1119 183 : fmd->fmd_flags &= ~FMD_FLAG_LABEL_IS_VXLAN_ID;
1120 : }
1121 :
1122 192 : return;
1123 : }
1124 :
1125 : static inline void
1126 127 : vr_fmd_set_label(struct vr_forwarding_md *fmd, unsigned int label,
1127 : unsigned int type)
1128 : {
1129 127 : fmd->fmd_label = label;
1130 127 : vr_fmd_update_label_type(fmd, type);
1131 :
1132 127 : return;
1133 : }
1134 :
1135 : static inline void
1136 2 : vr_fmd_update_l2_control_data(struct vr_forwarding_md *fmd, bool enable)
1137 : {
1138 2 : if (enable)
1139 0 : fmd->fmd_flags |= FMD_FLAG_L2_CONTROL_DATA;
1140 : else
1141 2 : fmd->fmd_flags &= ~FMD_FLAG_L2_CONTROL_DATA;
1142 :
1143 2 : return;
1144 : }
1145 :
1146 : static inline bool
1147 114 : vr_fmd_l2_control_data_is_enabled(struct vr_forwarding_md *fmd)
1148 : {
1149 114 : if (fmd->fmd_flags & FMD_FLAG_L2_CONTROL_DATA)
1150 0 : return true;
1151 :
1152 114 : return false;
1153 : }
1154 :
1155 : static inline uint16_t
1156 66 : vr_fmd_get_mirror_vlan(struct vr_forwarding_md *fmd)
1157 : {
1158 66 : if (fmd->fmd_mirror_data != FMD_MIRROR_INVALID_DATA) {
1159 0 : if (!(fmd->fmd_mirror_data & 0x8000))
1160 0 : return (fmd->fmd_mirror_data & 0x0FFF);
1161 : }
1162 :
1163 66 : return FMD_MIRROR_INVALID_DATA;
1164 : }
1165 :
1166 : static inline mirror_type_t
1167 0 : vr_fmd_get_mirror_type(struct vr_forwarding_md *fmd)
1168 : {
1169 0 : if (fmd->fmd_mirror_data != FMD_MIRROR_INVALID_DATA) {
1170 0 : if (fmd->fmd_mirror_data & 0x8000)
1171 0 : return (((fmd->fmd_mirror_data & 0x6000) >> 13) & 0x0003);
1172 : }
1173 :
1174 0 : return MIRROR_TYPE_UNKNOWN;
1175 : }
1176 :
1177 : static inline uint16_t
1178 2 : vr_fmd_get_mirror_if_id(struct vr_forwarding_md *fmd)
1179 : {
1180 2 : uint16_t intf_id = FMD_MIRROR_INVALID_DATA;
1181 :
1182 2 : if (fmd->fmd_mirror_data != FMD_MIRROR_INVALID_DATA) {
1183 0 : if (fmd->fmd_mirror_data & 0x8000) {
1184 0 : intf_id = fmd->fmd_mirror_data & 0x1FFF;
1185 0 : if (intf_id == 0x1FFF)
1186 0 : intf_id = FMD_MIRROR_INVALID_DATA;
1187 : }
1188 : }
1189 :
1190 2 : return intf_id;
1191 : }
1192 :
1193 : static inline void
1194 0 : vr_fmd_put_mirror_vlan(struct vr_forwarding_md *fmd, uint16_t vlan)
1195 : {
1196 0 : fmd->fmd_mirror_data = vlan & 0x0FFF;
1197 :
1198 0 : return;
1199 : }
1200 :
1201 :
1202 : static inline void
1203 2 : vr_fmd_put_mirror_type(struct vr_forwarding_md *fmd, mirror_type_t type)
1204 : {
1205 2 : uint16_t intf_id = vr_fmd_get_mirror_if_id(fmd);
1206 2 : fmd->fmd_mirror_data = 0x8000 | ((type & 0x3) << 13) | (intf_id & 0x1FFF);
1207 :
1208 2 : return;
1209 : }
1210 :
1211 : static inline void
1212 0 : vr_fmd_put_mirror_if_id(struct vr_forwarding_md *fmd, uint16_t if_id)
1213 : {
1214 0 : mirror_type_t type = vr_fmd_get_mirror_type(fmd);
1215 0 : fmd->fmd_mirror_data = 0x8000 | ((type & 0x3) << 13) | (if_id & 0x1FFF);
1216 :
1217 0 : return;
1218 : }
1219 :
1220 :
1221 : /*
1222 : * Size is : 2 Transport ports,
1223 : * IPV6 header which carried the above transport,
1224 : * ICMPV6 + IPV6 header generated by source of ICMP error,
1225 : * Fabric Tunnel headers, 2 ethernet headers and agent hdr
1226 : */
1227 : #define VR_AGENT_MIN_PACKET_LEN ((2 * sizeof(unsigned short)) + \
1228 : sizeof(struct vr_ip6) + \
1229 : sizeof(struct vr_icmp) + \
1230 : sizeof(struct vr_ip6) + VR_VXLAN_HDR_LEN + \
1231 : VR_L2_CTRL_DATA_LEN + \
1232 : (2 * VR_ETHER_HLEN) + sizeof(struct agent_hdr))
1233 :
1234 : static inline bool
1235 72 : pkt_is_gso(struct vr_packet *pkt)
1236 : {
1237 72 : if (vr_pgso_size && vr_pgso_size(pkt))
1238 0 : return true;
1239 72 : return false;
1240 : }
1241 :
1242 : static inline unsigned char *
1243 366 : pkt_data_at_offset(struct vr_packet *pkt, unsigned short off)
1244 : {
1245 366 : if (off < pkt->vp_end)
1246 366 : return pkt->vp_head + off;
1247 :
1248 0 : return vr_data_at_offset(pkt, off);
1249 : }
1250 :
1251 : static inline unsigned char *
1252 1896 : pkt_data(struct vr_packet *pkt)
1253 : {
1254 1896 : return pkt->vp_head + pkt->vp_data;
1255 : }
1256 :
1257 : static inline void
1258 : pkt_set_data(struct vr_packet *pkt, unsigned short off)
1259 : {
1260 : if (pkt->vp_data == off)
1261 : return;
1262 :
1263 : pkt->vp_data = off;
1264 : pkt->vp_len = pkt->vp_tail - pkt->vp_data;
1265 :
1266 : return;
1267 : }
1268 :
1269 : static inline void
1270 177 : pkt_set_inner_network_header(struct vr_packet *pkt, unsigned short off)
1271 : {
1272 177 : pkt->vp_inner_network_h = off;
1273 177 : return;
1274 : }
1275 :
1276 : static inline unsigned short
1277 62 : pkt_get_inner_network_header_off(struct vr_packet *pkt)
1278 : {
1279 62 : return pkt->vp_inner_network_h;
1280 :
1281 : }
1282 :
1283 : static inline unsigned char *
1284 28 : pkt_inner_network_header(struct vr_packet *pkt)
1285 : {
1286 28 : if (pkt->vp_inner_network_h < pkt->vp_end)
1287 28 : return pkt->vp_head + pkt->vp_inner_network_h;
1288 :
1289 0 : return NULL;
1290 : }
1291 :
1292 : static inline void
1293 240 : pkt_set_network_header(struct vr_packet *pkt, unsigned short off)
1294 : {
1295 240 : pkt->vp_network_h = off;
1296 240 : return;
1297 : }
1298 :
1299 : static inline unsigned short
1300 168 : pkt_get_network_header_off(struct vr_packet *pkt)
1301 : {
1302 168 : return pkt->vp_network_h;
1303 : }
1304 :
1305 : static inline unsigned char *
1306 874 : pkt_network_header(struct vr_packet *pkt)
1307 : {
1308 874 : if (pkt->vp_network_h < pkt->vp_end)
1309 874 : return pkt->vp_head + pkt->vp_network_h;
1310 :
1311 0 : return vr_network_header(pkt);
1312 : }
1313 :
1314 : static inline unsigned char *
1315 208 : pkt_pull(struct vr_packet *pkt, unsigned int len)
1316 : {
1317 208 : if (pkt->vp_data + len > pkt->vp_tail)
1318 0 : return NULL;
1319 :
1320 208 : pkt->vp_data += len;
1321 208 : pkt->vp_len -= len;
1322 :
1323 208 : return pkt_data(pkt);
1324 : }
1325 :
1326 : static inline unsigned char *
1327 0 : pkt_pull_tail(struct vr_packet *pkt, unsigned int len)
1328 : {
1329 0 : if (pkt->vp_tail + len > pkt->vp_end)
1330 0 : return NULL;
1331 :
1332 0 : pkt->vp_tail += len;
1333 0 : pkt->vp_len += len;
1334 :
1335 0 : return pkt->vp_head + pkt->vp_tail;
1336 : }
1337 :
1338 : static inline unsigned char *
1339 437 : pkt_push(struct vr_packet *pkt, unsigned int len)
1340 : {
1341 437 : if (len > pkt->vp_data)
1342 0 : return NULL;
1343 :
1344 437 : pkt->vp_data -= len;
1345 437 : pkt->vp_len += len;
1346 :
1347 437 : return pkt_data(pkt);
1348 : }
1349 :
1350 : static inline unsigned short
1351 1071 : pkt_head_len(struct vr_packet *pkt)
1352 : {
1353 1071 : return pkt->vp_len;
1354 : }
1355 :
1356 : static inline unsigned int
1357 771 : pkt_len(struct vr_packet *pkt)
1358 : {
1359 771 : return pkt_head_len(pkt) + vr_pfrag_len(pkt);
1360 : }
1361 :
1362 : static inline unsigned char *
1363 : pkt_reserve_head_space(struct vr_packet *pkt, unsigned short len)
1364 : {
1365 : if (pkt->vp_data + len > pkt->vp_end)
1366 : return NULL;
1367 :
1368 : if (pkt->vp_data == pkt->vp_tail)
1369 : pkt->vp_tail += len;
1370 :
1371 : if (pkt->vp_data + len > pkt->vp_tail)
1372 : return NULL;
1373 :
1374 : pkt->vp_data += len;
1375 :
1376 : return pkt_data(pkt);
1377 : }
1378 :
1379 : static inline unsigned short
1380 484 : pkt_head_space(struct vr_packet *pkt)
1381 : {
1382 484 : return pkt->vp_data;
1383 : }
1384 :
1385 : static inline bool
1386 33 : vr_is_ipv6_nd_packet(struct vr_packet *pkt)
1387 : {
1388 : struct vr_ip6 *ip6;
1389 : struct vr_icmp *icmp6;
1390 :
1391 33 : if (pkt->vp_type == VP_TYPE_IP6) {
1392 15 : ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
1393 15 : if (ip6->ip6_nxt == VR_IP_PROTO_ICMP6) {
1394 12 : icmp6 = (struct vr_icmp *)((unsigned char *)ip6 +
1395 : sizeof(struct vr_ip6));
1396 24 : return (icmp6->icmp_type >= VR_ICMP6_TYPE_ROUTER_SOL &&
1397 12 : icmp6->icmp_type <= VR_ICMP6_TYPE_REDIRECT);
1398 : }
1399 : }
1400 21 : return false;
1401 : }
1402 :
1403 : static inline void
1404 : pkt_init_fragment(struct vr_packet *dst, struct vr_packet *src)
1405 : {
1406 : dst->vp_if = src->vp_if;
1407 : dst->vp_nh = src->vp_nh;
1408 : dst->vp_cpu = src->vp_cpu;
1409 : dst->vp_flags = src->vp_flags;
1410 :
1411 : return;
1412 : }
1413 :
1414 : static inline void
1415 39 : pkt_drop_stats(struct vr_interface *vif, unsigned short reason, int cpu)
1416 : {
1417 : uint8_t *data;
1418 39 : unsigned int count = 1;
1419 39 : struct vrouter *router = vrouter_get(0);
1420 :
1421 : /*
1422 : * Lets log the errors as of now, till we are sure that nothing is
1423 : * un accounted
1424 : */
1425 39 : if (reason >= VP_DROP_MAX) {
1426 0 : vr_printf("Vrouter: vr_pdrop_stats invalid reason %d\n", reason);
1427 0 : return;
1428 : }
1429 :
1430 39 : if (cpu < 0) {
1431 0 : vr_printf("Vrouter: vr_pdrop_stats invalid CPU %d"
1432 : " reason %d\n", cpu, reason);
1433 0 : return;
1434 : }
1435 :
1436 : /* Lets increment the per cpu global stats */
1437 39 : if (router)
1438 39 : ((uint64_t *)(router->vr_pdrop_stats[cpu]))[reason]++;
1439 :
1440 : /* If vif is NULL, no accounting can be done against the vif. So return */
1441 39 : if (!vif)
1442 5 : return;
1443 :
1444 : /* Increment per cpu stats */
1445 34 : if (vif->vif_pcpu_drop_stats) {
1446 34 : data = vr_btable_get(vif->vif_pcpu_drop_stats,
1447 34 : ((cpu * VP_DROP_MAX) + reason));
1448 34 : if (data) {
1449 34 : count = ++(*data);
1450 34 : if (count < 255)
1451 34 : return;
1452 0 : *data = 0;
1453 : }
1454 : }
1455 :
1456 : /*
1457 : * Fall through, either for failure of per cpu stat or for carry
1458 : * over
1459 : */
1460 0 : if (vif->vif_drop_stats) {
1461 0 : (void)vr_sync_add_and_fetch_64u(vif->vif_drop_stats + reason, count);
1462 : }
1463 :
1464 0 : return;
1465 : }
1466 :
1467 : static inline bool
1468 0 : vr_pkt_is_bfd(struct vr_packet *pkt, uint8_t *bfd_state)
1469 : {
1470 : struct vr_ip *iph;
1471 : struct vr_udp *udph;
1472 : int pkt_off;
1473 : uint8_t *bfd_data;
1474 :
1475 0 : if (vr_pkt_is_ip(pkt)) {
1476 0 : iph = (struct vr_ip *)pkt_network_header(pkt);
1477 0 : if (iph->ip_proto == VR_IP_PROTO_UDP) {
1478 0 : pkt_off = pkt_get_network_header_off(pkt) + (iph->ip_hl << 2);
1479 0 : udph = (struct vr_udp *)(pkt_data_at_offset(pkt, pkt_off));
1480 0 : if (ntohs(udph->udp_dport) == VR_BFD_SINGLE_HOP_PORT) {
1481 0 : pkt_off += sizeof(struct vr_udp);
1482 0 : bfd_data = (uint8_t *)(pkt_data_at_offset(pkt, pkt_off));
1483 : // decode the BFD-state info from the packet
1484 0 : *bfd_state = bfd_data[1] & VR_BFD_STATE_FLAG_MASK;
1485 0 : return true;
1486 : }
1487 : }
1488 : }
1489 0 : return false;
1490 : }
1491 :
1492 : /* Below function logs the packet drops by getting packet information from vr_packet & vr_flow
1493 : * and logs in corresponding core */
1494 42 : static inline void vr_pkt_drop_log_func(unsigned short drop_reason, struct vr_packet *pkt,
1495 : struct vr_flow *flow, map_t file, unsigned int line)
1496 : {
1497 42 : int cpu = vr_get_cpu();
1498 42 : uint64_t m_sec = 0, n_sec = 0;
1499 42 : struct vr_ip *ip = NULL;
1500 42 : struct vr_ip6 *ip6 = NULL;
1501 :
1502 42 : struct vrouter *router = vrouter_get(0);
1503 42 : struct vr_pkt_drop_st *vr_pkt_drop = router->vr_pkt_drop;
1504 :
1505 : /* Copying index valjue from circular buffer of corresponding core*/
1506 42 : int buf_idx = vr_pkt_drop->vr_pkt_drop_log_buffer_index[cpu];
1507 42 : vr_pkt_drop_log_t **vr_pkt_drop_log_buffer = vr_pkt_drop->vr_pkt_drop_log;
1508 :
1509 : /* if Drop type is already set then droping other drop reasons
1510 : */
1511 42 : if ((vr_pkt_droplog_type != VP_DROP_MAX) &&
1512 0 : (vr_pkt_droplog_type != drop_reason)) {
1513 0 : return;
1514 : }
1515 :
1516 :
1517 42 : memset(vr_pkt_drop_log_buffer[cpu] + buf_idx, 0, sizeof(vr_pkt_drop_log_t));
1518 :
1519 : /* Check Packet drop log enabled at load time*/
1520 42 : if(vr_pkt_droplog_buf_en == 1)
1521 : {
1522 : /* Get the current time in epoch format */
1523 42 : vr_get_time(&m_sec, &n_sec);
1524 :
1525 : /* Copying epoch time into timestamp structure */
1526 42 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].timestamp, (unsigned int)m_sec)
1527 :
1528 42 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].drop_reason, drop_reason)
1529 :
1530 42 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].drop_loc.file, file)
1531 42 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].drop_loc.line, line)
1532 :
1533 42 : if(pkt != NULL)
1534 : {
1535 : /* Check if dropped packet is IPV6 */
1536 42 : if (pkt->vp_type == VP_TYPE_IP6)
1537 : {
1538 1 : ip6 = (struct vr_ip6 *)pkt_network_header(pkt);
1539 1 : if(!ip6)
1540 0 : return;
1541 1 : memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].src.ipv6.s6_addr, ip6->ip6_src,
1542 : sizeof(ip6->ip6_src));
1543 1 : memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].dst.ipv6.s6_addr, ip6->ip6_dst,
1544 : sizeof(ip6->ip6_dst));
1545 :
1546 1 : if(flow != NULL && flow->flow6_sport != 0) {
1547 0 : vr_pkt_drop_log_buffer[cpu][buf_idx].sport = flow->flow6_sport;
1548 0 : vr_pkt_drop_log_buffer[cpu][buf_idx].dport = flow->flow6_dport;
1549 : }
1550 : }
1551 : /* Check if dropped packet is IPV4*/
1552 41 : else if (pkt->vp_type != VP_TYPE_NULL) {
1553 41 : ip = (struct vr_ip *)pkt_network_header(pkt);
1554 41 : if(!ip)
1555 0 : return;
1556 :
1557 : /* Copying Source & destination address from IPV4 packet header*/
1558 41 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].src.ipv4.s_addr,
1559 : ip->ip_saddr)
1560 41 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].dst.ipv4.s_addr,
1561 : ip->ip_daddr)
1562 :
1563 : /* If flow is available, copy source port and destination port*/
1564 41 : if(flow != NULL && flow->flow4_sport != 0) {
1565 0 : vr_pkt_drop_log_buffer[cpu][buf_idx].sport = flow->flow4_sport;
1566 0 : vr_pkt_drop_log_buffer[cpu][buf_idx].dport = flow->flow4_dport;
1567 : }
1568 : }
1569 42 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].vp_type, pkt->vp_type)
1570 :
1571 : /* Log packet details into buffer, when drop least is diabled */
1572 42 : if(vr_pkt_droplog_min_sysctl_en != 1)
1573 : {
1574 0 : if(pkt->vp_if != NULL) {
1575 0 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].vif_idx,
1576 : pkt->vp_if->vif_idx)
1577 : }
1578 0 : if(pkt->vp_nh != NULL) {
1579 0 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].nh_id, pkt->vp_nh->nh_id)
1580 : }
1581 0 : PKT_LOG_FILL(vr_pkt_drop_log_buffer[cpu][buf_idx].pkt_len, pkt->vp_len)
1582 0 : if(pkt->vp_len < 100)
1583 0 : memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].pkt_header,
1584 0 : pkt_network_header(pkt), pkt->vp_len);
1585 : else
1586 0 : memcpy(vr_pkt_drop_log_buffer[cpu][buf_idx].pkt_header,
1587 0 : pkt_network_header(pkt), 100);
1588 : }
1589 : }
1590 : /* Circular buffer - buf_idx counter increments for every packet log, when it reaches max.
1591 : * configured value, it will start from zero and reach till max buffer size.
1592 : * circular buffer maintained for each core */
1593 42 : vr_pkt_drop->vr_pkt_drop_log_buffer_index[cpu] = ((++buf_idx) % vr_pkt_droplog_bufsz);
1594 : }
1595 : }
1596 :
1597 : #define MAX_BUF_SIZE 512
1598 : static inline void
1599 2 : pkt_dump (struct vr_packet *pkt)
1600 : {
1601 2 : int i = 0;
1602 : unsigned char *pstart;
1603 2 : char buf[MAX_BUF_SIZE] = {0};
1604 2 : int buf_off = 0, sz = 0;
1605 2 : int plen = 0;
1606 :
1607 2 : vr_printf("pkt %p head %p data %d len %d\n", pkt, pkt->vp_head,
1608 2 : pkt->vp_data, pkt->vp_len);
1609 2 : pstart = pkt_data(pkt);
1610 2 : plen = pkt_len(pkt);
1611 2 : if (pkt_data(pkt) == pkt_network_header(pkt)) {
1612 : // start from eth header
1613 2 : pstart -= 14;
1614 2 : plen += 14;
1615 : }
1616 86 : for (i = 0; i < plen; i++) {
1617 84 : if ((buf_off + 10) >= MAX_BUF_SIZE) {
1618 0 : break;
1619 : }
1620 84 : sz = sprintf(buf+buf_off, "0x%02x ", *(pstart + i));
1621 84 : if (sz < 0) break;
1622 84 : buf_off += sz;
1623 : }
1624 2 : vr_printf("pkt %p: %s\n", pkt, buf);
1625 2 : }
1626 :
1627 : #endif /* __VR_PACKET_H__ */
|