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