OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pkt_handler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "base/os.h"
6 #include <sys/types.h>
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9 #include <netinet/ip6.h>
10 #include <netinet/icmp6.h>
11 
12 #include "init/agent_param.h"
13 #include "cmn/agent_cmn.h"
14 #include "diag/diag.h"
15 #include "base/address_util.h"
16 #include "oper/ecmp_load_balance.h"
17 #include "oper/interface_common.h"
18 #include "oper/nexthop.h"
19 #include "oper/route_common.h"
20 #include "oper/vrf.h"
21 #include "oper/tunnel_nh.h"
22 #include "pkt/control_interface.h"
23 #include "pkt/pkt_handler.h"
24 #include "pkt/proto.h"
25 #include "pkt/flow_table.h"
26 #include "pkt/flow_proto.h"
27 #include "pkt/pkt_types.h"
28 #include "pkt/pkt_init.h"
29 #include "cmn/agent_stats.h"
30 #include "pkt/packet_buffer.h"
31 #include "vr_types.h"
32 #include "vr_defs.h"
33 #include "vr_mpls.h"
34 
35 #define PKT_TRACE(obj, arg) \
36 do { \
37  std::ostringstream _str; \
38  _str << arg; \
39  Pkt##obj::TraceMsg(PacketTraceBuf, __FILE__, __LINE__, _str.str()); \
40 } while (false) \
41 
42 const std::size_t PktTrace::kPktMaxTraceSize;
43 
45 namespace {
46 inline bool IsBfdkeepalivePkt(const AgentHdr &hdr)
47 {
48  // For the BFD traped packets, BFD state info is available in 'cmd_param'
49  if ((hdr.cmd == AGENT_TRAP_BFD) && (hdr.cmd_param == 0xc0)) {
50  return true;
51  }
52  return false;
53 }
54 
55 } // namespace
56 
57 PktHandler::PktHandler(Agent *agent, PktModule *pkt_module) :
58  stats_(), agent_(agent), pkt_module_(pkt_module),
59  work_queue_(TaskScheduler::GetInstance()->GetTaskId("Agent::PktHandler"), 0,
60  boost::bind(&PktHandler::ProcessPacket, this, _1)),
61  work_queue_bfd_ka_(TaskScheduler::GetInstance()->GetTaskId("Agent::BFD_KA"), 0,
62  boost::bind(&PktHandler::ProcessBfdDataPacket, this, _1))
63  {
64  work_queue_.set_name("Packet Handler Queue");
66  // BFD keep alive packet processing
67  work_queue_bfd_ka_.set_name("Packet BFD Data Queue");
69  for (int i = 0; i < MAX_MODULES; ++i) {
70  if (i == PktHandler::DHCP || i == PktHandler::DHCPV6 ||
71  i == PktHandler::DNS)
72  pkt_trace_.at(i).set_pkt_trace_size(512);
73  else
74  pkt_trace_.at(i).set_pkt_trace_size(128);
75  }
76 }
77 
80 }
81 
83  proto_list_.at(type) = proto;
84  if (type == BFD) {
85  bfd_keepalive_proto_ = proto;
86  }
87 }
88 
89 uint32_t PktHandler::EncapHeaderLen() const {
91 }
92 
93 // Send packet to tap interface
94 void PktHandler::Send(const AgentHdr &hdr, const PacketBufferPtr &buff) {
95  stats_.PktSent(PktHandler::PktModuleName(buff->module()));
96  pkt_trace_.at(buff->module()).AddPktTrace(PktTrace::Out, buff->data_len(),
97  buff->data(), &hdr);
98  if (agent_->pkt()->control_interface()->Send(hdr, buff) <= 0) {
99  PKT_TRACE(Err, "Error sending packet");
100  }
101  return;
102 }
103 
105  const Interface *in = NULL;
106  const VmInterface *intf = NULL;
107  const Interface *pkt_in_intf = NULL;
108  bool ingress= false;
110  uint8_t protocol;
111 
112  const NextHop *nh =
114  if (!nh) {
115  return;
116  }
117 
118  if (nh->GetType() == NextHop::INTERFACE) {
119  const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
120  in = intf_nh->GetInterface();
121  } else if (nh->GetType() == NextHop::VLAN) {
122  const VlanNH *vlan_nh = static_cast<const VlanNH *>(nh);
123  in = vlan_nh->GetInterface();
124  } else if (nh->GetType() == NextHop::COMPOSITE) {
125  const CompositeNH *comp_nh = static_cast<const CompositeNH *>(nh);
126 
127  if (comp_nh->composite_nh_type() == Composite::LOCAL_ECMP) {
128  in = comp_nh->GetFirstLocalEcmpMemberInterface();
129  }
130  }
131 
132  if (in) {
133  intf = dynamic_cast<const VmInterface *>(in);
134  }
135 
136  if (!intf) {
137  return;
138  }
139 
140  if (intf->fat_flow_list().list_.size() == 0) {
141  return;
142  }
143 
144  if (intf->ExcludeFromFatFlow(pkt->family, pkt->ip_saddr, pkt->ip_daddr)) {
145  return;
146  }
147  uint16_t sport = pkt->sport;
148  if (pkt->ip_proto == IPPROTO_ICMP || pkt->ip_proto == IPPROTO_IGMP) {
149  sport = 0;
150  }
151 
152  protocol = pkt->ip_proto;
153  /*
154  * For ICMPv6 change the protocol to ICMP as the same value is used when it is
155  * stored in the fat flow rule
156  */
157  if (pkt->ip_proto == IPPROTO_ICMPV6) {
158  protocol = IPPROTO_ICMP;
159  }
160 
161  pkt->is_fat_flow_src_prefix = false;
162  pkt->is_fat_flow_dst_prefix = false;
163 
164  if (pkt->sport < pkt->dport) {
165  if (intf->IsFatFlowPortBased(protocol, sport, &ignore_addr)) {
166  pkt->dport = 0;
167  pkt->ignore_address = ignore_addr;
168  return;
169  }
170 
171  if (intf->IsFatFlowPortBased(protocol, pkt->dport, &ignore_addr)) {
172  pkt->sport = 0;
173  pkt->ignore_address = ignore_addr;
174  return;
175  }
176  } else {
177  if (intf->IsFatFlowPortBased(protocol, pkt->dport, &ignore_addr)) {
178  if (pkt->dport == pkt->sport) {
179  pkt->same_port_number = true;
180  }
181  pkt->sport = 0;
182  pkt->ignore_address = ignore_addr;
183  return;
184  }
185 
186  if (intf->IsFatFlowPortBased(protocol, sport, &ignore_addr)) {
187  pkt->dport = 0;
188  pkt->ignore_address = ignore_addr;
189  return;
190  }
191  }
192  /* If Fat-flow port is 0, then both source and destination ports have to
193  * be ignored */
194  if (intf->IsFatFlowPortBased(protocol, 0, &ignore_addr)) {
195  pkt->sport = 0;
196  pkt->dport = 0;
197  pkt->ignore_address = ignore_addr;
198  return;
199  }
200 
201  // Check for fat flow based on prefix aggregation
203  pkt->agent_hdr.ifindex);
204  ingress = PktFlowInfo::ComputeDirection(pkt_in_intf);
205  // set the src and dst prefix to src & dst ip to begin with
206  pkt->ip_ff_src_prefix = pkt->ip_saddr;
207  pkt->ip_ff_dst_prefix = pkt->ip_daddr;
208  intf->IsFatFlowPrefixAggregation(ingress, protocol,
209  (uint16_t *)&pkt->sport,
210  (uint16_t *) &pkt->dport,
211  &pkt->same_port_number,
212  &pkt->ip_ff_src_prefix,
213  &pkt->ip_ff_dst_prefix,
216  &pkt->ignore_address);
217 }
218 
220  const Interface *intrface) {
221  if (intrface->type() == Interface::VM_INTERFACE &&
222  pkt_info->ip_proto == IPPROTO_UDP &&
223  (pkt_info->dport == BFD_SINGLEHOP_CONTROL_PORT ||
224  pkt_info->dport == BFD_MULTIHOP_CONTROL_PORT ||
225  pkt_info->dport == BFD_ECHO_PORT)) {
226  return true;
227  }
228 
229  return false;
230 }
231 
233  const Interface *intrface) {
234  if (intrface->type() == Interface::VM_INTERFACE &&
235  pkt_info->ip_proto == IPPROTO_ICMP) {
236  if (pkt_info->icmp_chksum == 0xffff) {
237  return true;
238  }
239  return pkt_info->is_segment_hc_pkt;
240  }
241  return false;
242 }
243 
244 // Validate the BFD Keepalive packet received
246  PktInfo *pkt_info,
247  uint8_t *pkt) {
248 
249  PktType::Type pkt_type = PktType::INVALID;
250  pkt_info->agent_hdr = hdr;
251 
252  int len = 0, ret = 0;
253 
254  // Parse packet before computing forwarding mode. Packet is parsed
255  // independent of packet forwarding mode
256  len += ParseEthernetHeader(pkt_info, (pkt + len));
257  if (pkt_info->ether_type != ETHERTYPE_IP) {
259  return INVALID;
260  }
261 
262  // IP Packets
263  ret = ParseIpPacket(pkt_info, pkt_type, (pkt + len));
264  if(ret == -1) {
265  return INVALID;
266  }
267  len += ret;
268 
269  // Check if the BFD KA packet
270  if (pkt_info->ip_proto == IPPROTO_UDP &&
271  pkt_info->dport == BFD_SINGLEHOP_CONTROL_PORT &&
272  (pkt_info->data[0] & 0x20)) {
273  return BFD;
274  }
275 
276  return INVALID;
277 }
278 
279 // Process the packet received from tap interface
281  PktInfo *pkt_info,
282  uint8_t *pkt) {
283  PktType::Type pkt_type = PktType::INVALID;
284  Interface *intf = NULL;
285 
286  pkt_info->agent_hdr = hdr;
287  if (!IsValidInterface(hdr.ifindex, &intf)) {
288  return INVALID;
289  }
290 
291  // Parse packet before computing forwarding mode. Packet is parsed
292  // indepndent of packet forwarding mode
293  if (ParseUserPkt(pkt_info, intf, pkt_type, pkt) < 0) {
294  return INVALID;
295  }
296 
297  if (pkt_info->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) {
298  // In case of a control packet from a TOR served by us, the ifindex
299  // is modified to index of the VM interface; validate this interface.
300  if (!IsValidInterface(pkt_info->agent_hdr.ifindex, &intf)) {
301  return INVALID;
302  }
303  }
304 
305  pkt_info->vrf = pkt_info->agent_hdr.vrf;
306 
307 
308  if (hdr.cmd == AgentHdr::TRAP_MAC_MOVE ||
309  hdr.cmd == AgentHdr::TRAP_MAC_LEARN ||
311  return MAC_LEARNING;
312  }
313 
314  bool is_flow_packet = IsFlowPacket(pkt_info);
315  // Look for DHCP packets if corresponding service is enabled
316  // Service processing over-rides ACL/Flow and forwarding configuration
317  if (!is_flow_packet && intf->dhcp_enabled() && (pkt_type == PktType::UDP)) {
318  if (pkt_info->ip && (pkt_info->dport == DHCP_SERVER_PORT ||
319  pkt_info->sport == DHCP_CLIENT_PORT)) {
320  return DHCP;
321  }
322  }
323  if (!is_flow_packet && intf->dhcp_enabled_v6() && (pkt_type == PktType::UDP)) {
324  if (pkt_info->ip6 && (pkt_info->dport == DHCPV6_SERVER_PORT ||
325  pkt_info->sport == DHCPV6_CLIENT_PORT)) {
326  return DHCPV6;
327  }
328  }
329 
330  // Handle ARP packet
331  if (pkt_type == PktType::ARP) {
332  return ARP;
333  }
334 
335  // Packets needing flow
336  if (is_flow_packet) {
337  CalculatePortIP(pkt_info);
338  if ((pkt_info->ip && pkt_info->family == Address::INET) ||
339  (pkt_info->ip6 && pkt_info->family == Address::INET6)) {
340  return FLOW;
341  } else {
342  PKT_TRACE(Err, "Flow trap for non-IP packet for interface "
343  "index <" << hdr.ifindex << ">");
345  return INVALID;
346  }
347  }
348 
349  // Look for DNS packets if corresponding service is enabled
350  // Service processing over-rides ACL/Flow
351  if (intf->dns_enabled() && (pkt_type == PktType::UDP)) {
352  if (pkt_info->dport == DNS_SERVER_PORT) {
353  return DNS;
354  }
355  }
356 
357  // Look for IP packets that need ARP resolution
358  if (pkt_info->ip && hdr.cmd == AgentHdr::TRAP_RESOLVE) {
359  return ARP;
360  }
361 
362  // send time exceeded ICMP messages to diag module
363  if (IsDiagPacket(pkt_info)) {
364  return DIAG;
365  }
366 
367  if (IsBFDHealthCheckPacket(pkt_info, intf)) {
368  return BFD;
369  }
370 
371  if (pkt_type == PktType::ICMP && IsSegmentHealthCheckPacket(pkt_info,
372  intf)) {
373  return DIAG;
374  }
375 
376  if (pkt_type == PktType::ICMP && IsGwPacket(intf, pkt_info->ip_daddr)) {
377  return ICMP;
378  }
379 
380  // Look for IP6 packets that need NDP resolution
381  if (pkt_info->ip6 && hdr.cmd == AgentHdr::TRAP_RESOLVE) {
382  return ICMPV6;
383  }
384 
385  if (pkt_type == PktType::ICMPV6) {
386  if (hdr.cmd == AgentHdr::TRAP_HANDLE_DF) {
387  return ICMPV6_ERROR;
388  }
389  return ICMPV6;
390  }
391 
392  if (pkt_type == PktType::IGMP) {
393  return IGMP;
394  }
395 
396  if(pkt_info->ip6 && hdr.cmd == AgentHdr::TRAP_HANDLE_DF) {
397  return ICMPV6_ERROR;
398  }
399 
400  if (pkt_info->ip && hdr.cmd == AgentHdr::TRAP_HANDLE_DF) {
401  return ICMP_ERROR;
402  }
403 
404  if (hdr.cmd == AgentHdr::TRAP_DIAG && (pkt_info->ip || pkt_info->ip6)) {
405  return DIAG;
406  }
407 
408  return INVALID;
409 }
410 
411 void PktHandler::HandleRcvPkt(const AgentHdr &hdr, const PacketBufferPtr &buff){
412  // Enqueue packets to a workqueue to decouple from ASIO and run in
413  // exclusion with DB
414  boost::shared_ptr<PacketBufferEnqueueItem>
415  info(new PacketBufferEnqueueItem(hdr, buff));
416 
417  // BFD Keepalive packets are enqueued to a seperate work queue
418  // so that its job run without dependence on dB tasks
419  if (IsBfdkeepalivePkt(hdr)) {
421  } else {
422  work_queue_.Enqueue(info);
423  }
424 }
425 
426 bool PktHandler::ProcessPacket(boost::shared_ptr<PacketBufferEnqueueItem> item) {
428  const AgentHdr &hdr = item->hdr;
429  const PacketBufferPtr &buff = item->buff;
430  boost::shared_ptr<PktInfo> pkt_info (new PktInfo(buff));
431  uint8_t *pkt = buff->data();
432  PktModuleName mod = ParsePacket(hdr, pkt_info.get(), pkt);
433  PktModuleEnqueue(mod, hdr, pkt_info, pkt);
434  if (mod == INVALID) {
435  pkt_info.reset();
436  }
437 
438  return true;
439 }
440 // Process BFD keepalives (BFD packets with state 'UP') in a seperate task
441 // that is independent of Db Task
442 bool PktHandler::ProcessBfdDataPacket(boost::shared_ptr<PacketBufferEnqueueItem> item) {
443  const AgentHdr &hdr = item->hdr;
444  const PacketBufferPtr &buff = item->buff;
445  uint8_t *pkt = buff->data();
446  PktModuleName mod;
447 
448  // In certain Agent restart race condition, Agent would restart but
449  // vrouter is not in sync yet with agent restart. In this condition
450  // there could be BFD packets from the prior session could be trapped
451  // in vrouter and injected to the Agent's PKT0 i/f So, don't process
452  // BFD packets received, prior to agent init done.
453  if (!bfd_keepalive_proto_ || (agent_->init_done() == false)) {
454  PKT_TRACE(Err, "BFD proto_list is not Initialized. Ignoring");
455  return true;
456  }
457 
458  boost::shared_ptr<PktInfo> pkt_info (new PktInfo(buff));
459  mod = ParseBfdDataPacket(hdr, pkt_info.get(), pkt);
460  if (mod == BFD) {
461  pkt_info->is_bfd_keepalive = true;
462  pkt_info->packet_buffer()->set_module(mod);
463  bfd_keepalive_proto_->Enqueue(pkt_info);
464  proto_list_.at(BFD)->ProcessStats(PktStatsType::PKT_RX_ENQUEUE);
465  } else {
467  pkt_info.reset();
468  }
469  return true;
470 }
471 
473  boost::shared_ptr<PktInfo> pkt_info,
474  uint8_t * pkt) {
475  pkt_info->packet_buffer()->set_module(mod);
476  stats_.PktRcvd(mod);
477  if (mod == INVALID) {
479  pkt_trace_.at(mod).AddPktTrace(PktTrace::In, pkt_info->len, pkt, &hdr);
480  return;
481  }
482  Enqueue(mod, pkt_info);
483 }
484 
485 // Compute L2/L3 forwarding mode for pacekt.
486 // Forwarding mode is L3 if,
487 // - Packet uses L3 label
488 // - DMAC in packet is VRRP Mac or VHOST MAC or receiving physical interface MAC
489 // Else forwarding mode is L2
491  const Interface *intf) const {
492  if (pkt_info->tunnel.type.GetType() == TunnelType::MPLS_GRE ||
493  pkt_info->tunnel.type.GetType() == TunnelType::MPLS_UDP) {
494  return pkt_info->l3_label;
495  }
496 
497  if (pkt_info->dmac == agent_->vrrp_mac()) {
498  return true;
499  }
500 
501  if (pkt_info->dmac == agent_->vhost_interface()->mac()) {
502  return true;
503  }
504 
505  if (intf && intf->type() == Interface::PHYSICAL &&
506  pkt_info->dmac == intf->mac()) {
507  return true;
508  }
509 
510  return false;
511 }
512 
513 void PktHandler::SetOuterIp(PktInfo *pkt_info, uint8_t *pkt) {
514  if (pkt_info->ether_type != ETHERTYPE_IP) {
515  return;
516  }
517  struct ip *ip_hdr = (struct ip *)pkt;
518  pkt_info->tunnel.ip = ip_hdr;
519  pkt_info->tunnel.ip_saddr = ntohl(ip_hdr->ip_src.s_addr);
520  pkt_info->tunnel.ip_daddr = ntohl(ip_hdr->ip_dst.s_addr);
521 }
522 
524  pkt_info->tunnel.eth = pkt_info->eth;
525 }
526 
527 
528 int PktHandler::ParseEthernetHeader(PktInfo *pkt_info, uint8_t *pkt) {
529  int len = 0;
530  pkt_info->eth = (struct ether_header *) (pkt + len);
531  pkt_info->smac = MacAddress(pkt_info->eth->ether_shost);
532  pkt_info->dmac = MacAddress(pkt_info->eth->ether_dhost);
533  pkt_info->ether_type = ntohs(pkt_info->eth->ether_type);
534  len += sizeof(struct ether_header);
535 
536  //strip service vlan and customer vlan in packet
537  while (pkt_info->ether_type == ETHERTYPE_VLAN ||
538  pkt_info->ether_type == ETHERTYPE_QINQ) {
539  pkt_info->ether_type = ntohs(*((uint16_t *)(pkt + len + 2)));
540  len += VLAN_HDR_LEN;
541  }
542 
543  if (pkt_info->ether_type == ETHERTYPE_PBB) {
544  //Parse inner payload
545  pkt_info->pbb_header = (uint32_t *)(pkt + len);
546  pkt_info->b_smac = pkt_info->smac;
547  pkt_info->b_dmac = pkt_info->dmac;
548  pkt_info->i_sid = ntohl(*(pkt_info->pbb_header)) & 0x00FFFFFF;
549  len += ParseEthernetHeader(pkt_info, pkt + len + PBB_HEADER_LEN);
550  }
551 
552  return len;
553 }
554 
556  uint8_t *pkt) {
557  int len = 0;
558  uint16_t ip_payload_len = 0;
559  if (pkt_info->ether_type == ETHERTYPE_IP) {
560  struct ip *ip = (struct ip *)(pkt + len);
561  pkt_info->ip = ip;
562  pkt_info->family = Address::INET;
563  pkt_info->ip_saddr = IpAddress(Ip4Address(ntohl(ip->ip_src.s_addr)));
564  pkt_info->ip_daddr = IpAddress(Ip4Address(ntohl(ip->ip_dst.s_addr)));
565  pkt_info->ip_proto = ip->ip_p;
566  pkt_info->ttl = ip->ip_ttl;
567  uint8_t ip_header_len = (ip->ip_hl << 2);
568  ip_payload_len = ip->ip_len - ip_header_len;
569  len += ip_header_len;
570  } else if (pkt_info->ether_type == ETHERTYPE_IPV6) {
571  pkt_info->family = Address::INET6;
572  ip6_hdr *ip = (ip6_hdr *)(pkt + len);
573  pkt_info->ip6 = ip;
574  pkt_info->ip = NULL;
575  Ip6Address::bytes_type addr;
576 
577  for (int i = 0; i < 16; i++) {
578  addr[i] = ip->ip6_src.s6_addr[i];
579  }
580  pkt_info->ip_saddr = IpAddress(Ip6Address(addr));
581 
582  for (int i = 0; i < 16; i++) {
583  addr[i] = ip->ip6_dst.s6_addr[i];
584  }
585  pkt_info->ip_daddr = IpAddress(Ip6Address(addr));
586  pkt_info->ttl = ip->ip6_hlim;
587 
588  uint8_t proto = ip->ip6_ctlun.ip6_un1.ip6_un1_nxt;
589  len += sizeof(ip6_hdr);
590  if (proto == IPPROTO_FRAGMENT) {
591  ip6_frag *nxt = (ip6_frag *)(pkt + len);
592  proto = nxt->ip6f_nxt;
593  len += sizeof(ip6_frag);
594  }
595 
596  pkt_info->ip_proto = proto;
597  } else {
598  LOG(ERROR,
599  "Error EthType = Non IP/IPv6. BackTrace: " << AgentBackTrace(1));
601  return -1;
602  }
603 
604  switch (pkt_info->ip_proto) {
605  case IPPROTO_UDP : {
606  pkt_info->transp.udp = (udphdr *) (pkt + len);
607  len += sizeof(udphdr);
608  pkt_info->data = (pkt + len);
609 
610  pkt_info->dport = ntohs(pkt_info->transp.udp->uh_dport);
611  pkt_info->sport = ntohs(pkt_info->transp.udp->uh_sport);
612  pkt_type = PktType::UDP;
613  break;
614  }
615 
616  case IPPROTO_TCP : {
617  pkt_info->transp.tcp = (tcphdr *) (pkt + len);
618  len += sizeof(tcphdr);
619  pkt_info->data = (pkt + len);
620 
621  pkt_info->dport = ntohs(pkt_info->transp.tcp->th_dport);
622  pkt_info->sport = ntohs(pkt_info->transp.tcp->th_sport);
623  pkt_info->tcp_ack = pkt_info->transp.tcp->th_flags & TH_ACK;
624  pkt_type = PktType::TCP;
625  break;
626  }
627 
628  case IPPROTO_SCTP : {
629  pkt_info->transp.sctp = (sctphdr *) (pkt + len);
630  len += sizeof(sctphdr);
631  pkt_info->data = (pkt + len);
632  pkt_info->dport = ntohs(pkt_info->transp.sctp->th_dport);
633  pkt_info->sport = ntohs(pkt_info->transp.sctp->th_sport);
634  pkt_type = PktType::SCTP;
635  break;
636  }
637 
638  case IPPROTO_ICMP: {
639  pkt_info->transp.icmp = (struct icmp *) (pkt + len);
640  pkt_type = PktType::ICMP;
641 
642  struct icmp *icmp = (struct icmp *)(pkt + len);
643  pkt_info->icmp_chksum = icmp->icmp_cksum;
644  pkt_info->dport = htons(icmp->icmp_type);
645  if (icmp->icmp_type == ICMP_ECHO || icmp->icmp_type == ICMP_ECHOREPLY) {
646  pkt_info->dport = ICMP_ECHOREPLY;
647  pkt_info->sport = htons(icmp->icmp_id);
648  pkt_info->data = (pkt + len + ICMP_MINLEN);
649  uint16_t icmp_payload_len = ip_payload_len - ICMP_MINLEN;
650  if (icmp_payload_len >= sizeof(AgentDiagPktData)) {
651  AgentDiagPktData *ad = (AgentDiagPktData *)pkt_info->data;
652  string value(ad->data_, (sizeof(ad->data_) - 1));
653  if (value.compare(0, (sizeof(ad->data_) - 1),
654  DiagTable::kDiagData) == 0) {
655  pkt_info->is_segment_hc_pkt = true;
656  }
657  }
658  } else if (IsFlowPacket(pkt_info) &&
659  ((icmp->icmp_type == ICMP_DEST_UNREACH) ||
660  (icmp->icmp_type == ICMP_TIME_EXCEEDED))) {
661  //Agent has to look at inner payload
662  //and recalculate the parameter
663  //Handle this only for packets requiring flow miss
664  if(ParseIpPacket(pkt_info, pkt_type, pkt + len + sizeof(icmp)) == -1) {
665  return -1;
666  }
667  //Swap the key parameter, which would be used as key
668  IpAddress src_ip = pkt_info->ip_saddr;
669  pkt_info->ip_saddr = pkt_info->ip_daddr;
670  pkt_info->ip_daddr = src_ip;
671  if (pkt_info->ip_proto != IPPROTO_ICMP) {
672  uint16_t port = pkt_info->sport;
673  pkt_info->sport = pkt_info->dport;
674  pkt_info->dport = port;
675  }
676  } else {
677  pkt_info->sport = 0;
678  }
679  break;
680  }
681 
682  case IPPROTO_ICMPV6: {
683  pkt_type = PktType::ICMPV6;
684  icmp6_hdr *icmp = (icmp6_hdr *)(pkt + len);
685  pkt_info->transp.icmp6 = icmp;
686 
687  pkt_info->dport = htons(icmp->icmp6_type);
688  if (icmp->icmp6_type == ICMP6_ECHO_REQUEST ||
689  icmp->icmp6_type == ICMP6_ECHO_REPLY) {
690  pkt_info->dport = ICMP6_ECHO_REPLY;
691  pkt_info->sport = htons(icmp->icmp6_id);
692  } else if (IsFlowPacket(pkt_info) &&
693  icmp->icmp6_type < ICMP6_ECHO_REQUEST) {
694  //Agent has to look at inner payload
695  //and recalculate the parameter
696  //Handle this only for packets requiring flow miss
697  if(ParseIpPacket(pkt_info, pkt_type, pkt + len + sizeof(icmp)) == -1) {
698  return -1;
699  }
700  //Swap the key parameter, which would be used as key
701  IpAddress src_ip = pkt_info->ip_saddr;
702  pkt_info->ip_saddr = pkt_info->ip_daddr;
703  pkt_info->ip_daddr = src_ip;
704  if (pkt_info->ip_proto != IPPROTO_ICMPV6) {
705  uint16_t port = pkt_info->sport;
706  pkt_info->sport = pkt_info->dport;
707  pkt_info->dport = port;
708  }
709  } else {
710  pkt_info->sport = 0;
711  }
712  break;
713  }
714 
715  case IPPROTO_IGMP: {
716  pkt_info->transp.igmp = (struct igmp *) (pkt + len);
717  pkt_type = PktType::IGMP;
718 
719  pkt_info->dport = 0;
720  pkt_info->sport = 0;
721  pkt_info->data = (pkt + len);
722  break;
723  }
724 
725  default: {
726  pkt_type = PktType::IP;
727  pkt_info->dport = 0;
728  pkt_info->sport = 0;
729  break;
730  }
731  }
732 
733  return len;
734 }
735 
736 int PktHandler::ParseControlWord(PktInfo *pkt_info, uint8_t *pkt,
737  const MplsLabel *mpls) {
738  uint32_t ret = 0;
739  if (mpls->IsFabricMulticastReservedLabel() == true) {
740  //Check if there is a control word
741  uint32_t *control_word = (uint32_t *)(pkt);
742  if (*control_word == kMulticastControlWord) {
743  pkt_info->l3_label = false;
744  ret += kMulticastControlWordSize + sizeof(VxlanHdr) +
745  sizeof(udphdr) + sizeof(ip);
746  }
747  } else if (pkt_info->l3_label == false) {
748  bool layer2_control_word = false;
749  const InterfaceNH *intf_nh =
750  dynamic_cast<const InterfaceNH *>(mpls->nexthop());
751  if (intf_nh && intf_nh->layer2_control_word()) {
752  layer2_control_word = true;
753  }
754 
755  const CompositeNH *comp_nh =
756  dynamic_cast<const CompositeNH *>(mpls->nexthop());
757  if (comp_nh && comp_nh->layer2_control_word()) {
758  layer2_control_word = true;
759  }
760 
761  const VrfNH *vrf_nh =
762  dynamic_cast<const VrfNH *>(mpls->nexthop());
763  if (vrf_nh && vrf_nh->layer2_control_word()) {
764  layer2_control_word = true;
765  }
766 
767  //Check if there is a control word
768  uint32_t *control_word = (uint32_t *)(pkt);
769  if (layer2_control_word && *control_word == kMulticastControlWord) {
771  }
772  }
773 
774  return ret;
775 }
776 
777 int PktHandler::ParseMplsHdr(PktInfo *pkt_info, uint8_t *pkt) {
778  MplsHdr *hdr = (MplsHdr *)(pkt);
779 
780  // MPLS Header validation. Check for,
781  // - There is single label
782  uint32_t mpls_host = ntohl(hdr->hdr);
783  pkt_info->tunnel.label = (mpls_host & 0xFFFFF000) >> 12;
784  uint32_t ret = sizeof(MplsHdr);
785 
786  if ((mpls_host & 0x100) == 0) {
787  // interpret outer label 0xffffff as no label
788  if (((mpls_host & 0xFFFFF000) >> 12) !=
791  PKT_TRACE(Err, "Unexpected MPLS Label Stack. Ignoring");
792  return -1;
793  }
794  hdr = (MplsHdr *) (pkt + 4);
795  mpls_host = ntohl(hdr->hdr);
796  pkt_info->tunnel.label = (mpls_host & 0xFFFFF000) >> 12;
797  if ((mpls_host & 0x100) == 0) {
799  PKT_TRACE(Err, "Unexpected MPLS Label Stack. Ignoring");
800  return -1;
801  }
802  ret += sizeof(MplsHdr);
803 
804  }
805 
806  uint32_t label = pkt_info->tunnel.label;
807  MplsLabelKey mpls_key(label);
808 
809  const MplsLabel *mpls = static_cast<const MplsLabel *>(
810  agent_->mpls_table()->FindActiveEntry(&mpls_key));
811  if (mpls == NULL) {
812  PKT_TRACE(Err, "Invalid MPLS Label <" << label << ">. Ignoring");
814  return -1;
815  }
816 
817  pkt_info->l3_label = true;
818  const InterfaceNH *nh = dynamic_cast<const InterfaceNH *>(mpls->nexthop());
819  if (nh && nh->IsBridge()) {
820  pkt_info->l3_label = false;
821  }
822 
823  const CompositeNH *cnh = dynamic_cast<const CompositeNH *>(mpls->nexthop());
824  if (cnh && cnh->composite_nh_type() != Composite::LOCAL_ECMP) {
825  pkt_info->l3_label = false;
826  }
827 
828  const VrfNH *vrf_nh = dynamic_cast<const VrfNH *>(mpls->nexthop());
829  if (vrf_nh && vrf_nh->bridge_nh() == true) {
830  pkt_info->l3_label = false;
831  }
832 
833  ret += ParseControlWord(pkt_info, pkt + ret, mpls);
834  return ret;
835 }
836 
837 // Parse MPLSoGRE header
838 int PktHandler::ParseMPLSoGRE(PktInfo *pkt_info, uint8_t *pkt) {
839  GreHdr *gre = (GreHdr *)(pkt);
840  if (gre->protocol != ntohs(VR_GRE_PROTO_MPLS)) {
841  PKT_TRACE(Err, "Non-MPLS protocol <" << ntohs(gre->protocol) <<
842  "> in GRE header");
843  return -1;
844  }
845 
846  int len = sizeof(GreHdr);
847 
848  int tmp;
849  tmp = ParseMplsHdr(pkt_info, (pkt + len));
850  if (tmp < 0) {
851  return tmp;
852  }
853  len += tmp;
854 
855  if (pkt_info->l3_label == false) {
856  tmp = ParseEthernetHeader(pkt_info, (pkt + len));
857  if (tmp < 0)
858  return tmp;
859  len += tmp;
860  }
861 
863  return (len);
864 }
865 
866 int PktHandler::ParseMPLSoUDP(PktInfo *pkt_info, uint8_t *pkt) {
867  int len = ParseMplsHdr(pkt_info, pkt);
868  if (len < 0) {
869  return len;
870  }
871 
872  if (pkt_info->l3_label == false) {
873  len += ParseEthernetHeader(pkt_info, (pkt + len));
874  }
875 
877  return len;
878 }
879 
880 int PktHandler::ParseVxlan(PktInfo *pkt_info, uint8_t *pkt) {
881  VxlanHdr *vxlan = (VxlanHdr *)(pkt);
882  pkt_info->tunnel.vxlan_id = htonl(vxlan->vxlan_id) >> 8;
883 
884  int len = sizeof(vxlan);
885  len += ParseEthernetHeader(pkt_info, (pkt + len));
886 
888  pkt_info->l3_label = false;
889  return len;
890 }
891 
892 int PktHandler::ParseUDPTunnels(PktInfo *pkt_info, uint8_t *pkt) {
893  int len = 0;
894  if (pkt_info->dport == VXLAN_UDP_DEST_PORT)
895  len = ParseVxlan(pkt_info, (pkt + len));
896  else if (pkt_info->dport == MPLS_OVER_UDP_DEST_PORT ||
897  pkt_info->dport == IANA_MPLS_OVER_UDP_DEST_PORT)
898  len = ParseMPLSoUDP(pkt_info, (pkt + len));
899 
900  return len;
901 }
902 
904  // For ICMP, IGMP, make sure IP is IPv4, else fail the parsing
905  // so that we don't go ahead and access the ip header later
906  if (((pkt_info->ip_proto == IPPROTO_ICMP) ||
907  (pkt_info->ip_proto == IPPROTO_IGMP)) && (!pkt_info->ip)) {
908  return false;
909  }
910  // If ip proto is ICMPv6, then make sure IP is IPv6, else fail
911  // the parsing so that we don't go ahead and access the ip6 header
912  // later
913  if ((pkt_info->ip_proto == IPPROTO_ICMPV6) && (!pkt_info->ip6)) {
914  return false;
915  }
916  return true;
917 }
918 
920  PktType::Type &pkt_type, uint8_t *pkt) {
921  int len = 0, ret = 0;
922  bool pkt_ok;
923 
924  // get to the actual packet header
925  len += ParseEthernetHeader(pkt_info, (pkt + len));
926 
927  // Parse payload
928  if (pkt_info->ether_type == ETHERTYPE_ARP) {
929  pkt_info->arp = (ether_arp *) (pkt + len);
930  pkt_type = PktType::ARP;
931  union {
932  uint8_t data[sizeof(in_addr_t)];
933  in_addr_t addr;
934  } bytes;
935  memcpy(bytes.data, pkt_info->arp->arp_spa, sizeof(in_addr_t));
936  in_addr_t spa = ntohl(bytes.addr);
937  pkt_info->ip_saddr = IpAddress(Ip4Address(spa));
938  return len;
939  }
940 
941  // Identify NON-IP Packets
942  if (pkt_info->ether_type != ETHERTYPE_IP &&
943  pkt_info->ether_type != ETHERTYPE_IPV6) {
944  pkt_info->data = (pkt + len);
945  pkt_type = PktType::NON_IP;
946  return len;
947  }
948  // Copy IP fields from outer header assuming tunnel is present. If tunnel
949  // is not present, the values here will be ignored
950  SetOuterMac(pkt_info);
951  SetOuterIp(pkt_info, (pkt + len));
952 
953  // IP Packets
954  ret = ParseIpPacket(pkt_info, pkt_type, (pkt + len));
955  if(ret == -1) {
956  return -1;
957  }
958  len += ret;
959 
960  if (!ValidateIpPacket(pkt_info)) {
962  return -1;
963  }
964 
965  // If packet is an IP fragment and not flow trap, ignore it
966  if (IgnoreFragmentedPacket(pkt_info)) {
968  return -1;
969  }
970 
971  // If it is a packet from TOR that we serve, dont parse any further
972  if (IsManagedTORPacket(intf, pkt_info, pkt_type, (pkt + len), &pkt_ok)) {
973  return len;
974  } else if (!pkt_ok) {
975  // invalid pkt received from tor
977  return -1;
978  }
979 
980  if (IsDiagPacket(pkt_info) &&
981  (pkt_info->agent_hdr.cmd != AgentHdr::TRAP_ROUTER_ALERT)) {
982  return len;
983  }
984 
985  // If tunneling is not enabled on interface or if it is a DHCP packet,
986  // dont parse any further
987 // if (intf->IsTunnelEnabled() == false || IsDHCPPacket(pkt_info)) {
988  if (intf->IsTunnelEnabled() == false) {
990  return len;
991  }
992  else if (IsDHCPPacket(pkt_info)) {
993  return len;
994  }
995 
996  int tunnel_len = 0;
997  // Do tunnel processing only if IP-DA is ours
998  if (pkt_info->family == Address::INET &&
999  pkt_info->ip_daddr.to_v4() == agent_->router_id()) {
1000  // Look for supported headers
1001  switch (pkt_info->ip_proto) {
1002  case IPPROTO_GRE :
1003  // Parse MPLSoGRE tunnel
1004  tunnel_len = ParseMPLSoGRE(pkt_info, (pkt + len));
1005  break;
1006 
1007  case IPPROTO_UDP:
1008  // Parse MPLSoUDP tunnel
1009  tunnel_len = ParseUDPTunnels(pkt_info, (pkt + len));
1010  break;
1011 
1012  default:
1013  break;
1014  }
1015  }
1016 
1017  if (tunnel_len < 0) {
1018  // Found tunnel packet, but error in decoding
1019  pkt_type = PktType::INVALID;
1021  return tunnel_len;
1022  }
1023 
1024  if (tunnel_len == 0) {
1025  return len;
1026  }
1027 
1028  len += tunnel_len;
1029 
1030  // Find IPv4/IPv6 Packet based on first nibble in payload
1031  if (((pkt + len)[0] & 0x60) == 0x60) {
1032  pkt_info->ether_type = ETHERTYPE_IPV6;
1033  } else {
1034  pkt_info->ether_type = ETHERTYPE_IP;
1035  }
1036 
1037 
1038  ret = ParseIpPacket(pkt_info, pkt_type, (pkt + len));
1039  if(ret == -1) {
1040  return -1;
1041  }
1042  len += ret;
1043 
1044  // validate inner iphdr
1045  if (!ValidateIpPacket(pkt_info)) {
1047  return -1;
1048  }
1049 
1050  return len;
1051 }
1052 
1053 // Enqueue an inter-task message to the specified module
1055  if (mod < MAX_MODULES) {
1056  boost::shared_ptr<PktInfo> pkt_info(new PktInfo(mod, msg));
1057  if (!(proto_list_.at(mod)->Enqueue(pkt_info))) {
1058  PKT_TRACE(Err, "Threshold exceeded while enqueuing IPC Message <" <<
1059  mod << ">");
1060  }
1061  }
1062 }
1063 
1065  if (pkt_info->ip) {
1066  uint16_t offset = htons(pkt_info->ip->ip_off);
1067  if (((offset & IP_MF) || (offset & IP_OFFMASK)) &&
1068  !IsFlowPacket(pkt_info))
1069  return true;
1070  } else if (pkt_info->ip6) {
1071  uint8_t proto = pkt_info->ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
1072  if (proto == IPPROTO_FRAGMENT) {
1073  if (IsFlowPacket(pkt_info) ||
1074  pkt_info->agent_hdr.cmd == AgentHdr::TRAP_HANDLE_DF) {
1075  return false;
1076  } else {
1077  return true;
1078  }
1079  }
1080  }
1081 
1082  return false;
1083 }
1084 
1086  // Do not consider source port in case we are looking at UDP tunnel header
1087  if (pkt_info->dport == VXLAN_UDP_DEST_PORT ||
1088  pkt_info->dport == MPLS_OVER_UDP_DEST_PORT ||
1089  pkt_info->dport == IANA_MPLS_OVER_UDP_DEST_PORT) {
1090  return false;
1091  }
1092 
1093  if (pkt_info->dport == DHCP_SERVER_PORT ||
1094  pkt_info->sport == DHCP_CLIENT_PORT) {
1095  // we dont handle DHCPv6 coming from fabric
1096  return true;
1097  }
1098  return false;
1099 }
1100 
1101 bool PktHandler::IsToRDevice(uint32_t vrf_id, const IpAddress &ip) {
1102  if (agent()->tsn_enabled() == false)
1103  return false;
1104 
1105  if (ip.is_v4() == false)
1106  return false;
1107  Ip4Address ip4 = ip.to_v4();
1108 
1109  VrfEntry *vrf = agent()->vrf_table()->FindVrfFromId(vrf_id);
1110  if (vrf == NULL)
1111  return false;
1112 
1113  BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
1114  (vrf->GetBridgeRouteTable());
1115  if (table == NULL)
1116  return false;
1117 
1119  if (rt == NULL)
1120  return false;
1121 
1122  const CompositeNH *nh = dynamic_cast<const CompositeNH *>
1123  (rt->GetActiveNextHop());
1124  if (nh == NULL)
1125  return false;
1126 
1127  ComponentNHList::const_iterator it = nh->begin();
1128  while (it != nh->end()) {
1129  const CompositeNH *tor_nh = dynamic_cast<const CompositeNH *>
1130  ((*it)->nh());
1131  if (tor_nh == NULL) {
1132  it++;
1133  continue;
1134  }
1135 
1136  if (tor_nh->composite_nh_type() != Composite::TOR &&
1137  tor_nh->composite_nh_type() != Composite::EVPN) {
1138  it++;
1139  continue;
1140  }
1141 
1142  ComponentNHList::const_iterator tor_it = tor_nh->begin();
1143  while (tor_it != tor_nh->end()) {
1144  const TunnelNH *tun_nh = dynamic_cast<const TunnelNH *>
1145  ((*tor_it)->nh());
1146  if (tun_nh == NULL) {
1147  tor_it++;
1148  continue;
1149  }
1150  if (*tun_nh->GetDip() == ip4) {
1151  return true;
1152  }
1153  tor_it++;
1154  }
1155 
1156  it++;
1157  }
1158 
1159  return false;
1160 }
1161 
1162 // We can receive DHCP / DNS packets on physical port from TOR ports managed
1163 // by a TOR services node. Check if the source mac is the mac address of a
1164 // VM interface available in the node.
1166  PktType::Type &pkt_type, uint8_t *pkt, bool *pkt_ok) {
1167  *pkt_ok = true;
1168  if (intf->type() != Interface::PHYSICAL) {
1169  return false;
1170  }
1171 
1172  if (pkt_type != PktType::UDP || pkt_info->dport != VXLAN_UDP_DEST_PORT)
1173  return false;
1174 
1175  // Get VXLAN id and point to original L2 frame after the VXLAN header
1176  pkt += 8;
1177 
1178  // get to the actual packet header
1179  pkt += ParseEthernetHeader(pkt_info, pkt);
1180 
1181  ether_addr addr;
1182  memcpy(addr.ether_addr_octet, pkt_info->eth->ether_shost, ETH_ALEN);
1183  MacAddress address(addr);
1184  const VrfEntry *vrf = agent_->vrf_table()->
1185  FindVrfFromId(pkt_info->agent_hdr.vrf);
1186  if (vrf == NULL)
1187  return false;
1188  BridgeAgentRouteTable *bridge_table =
1189  dynamic_cast<BridgeAgentRouteTable *>(vrf->GetBridgeRouteTable());
1190  if(bridge_table == NULL) {
1191  LOG(ERROR,
1192  "Error bridge_table == NULL. BackTrace: " << AgentBackTrace(1));
1193  _Exit(0);
1194  }
1195  const VmInterface *vm_intf = bridge_table->FindVmFromDhcpBinding(address);
1196  if (vm_intf == NULL) {
1197  return false;
1198  }
1199 
1200  if (IsToRDevice(vm_intf->vrf_id(), pkt_info->ip_saddr) == false) {
1201  return false;
1202  }
1203 
1204  // update agent_hdr to reflect the VM interface data
1205  // cmd_param is set to physical interface id
1207  pkt_info->agent_hdr.cmd_param = pkt_info->agent_hdr.ifindex;
1208  pkt_info->agent_hdr.ifindex = vm_intf->id();
1209 
1210  // Parse payload
1211  if (pkt_info->ether_type == ETHERTYPE_ARP) {
1212  pkt_info->arp = (ether_arp *) pkt;
1213  pkt_type = PktType::ARP;
1214  return true;
1215  }
1216 
1217  // Identify NON-IP Packets
1218  if (pkt_info->ether_type != ETHERTYPE_IP &&
1219  pkt_info->ether_type != ETHERTYPE_IPV6) {
1220  pkt_info->data = pkt;
1221  pkt_type = PktType::NON_IP;
1222  return true;
1223  }
1224 
1225  // IP Packets
1226  if(ParseIpPacket(pkt_info, pkt_type, pkt) == -1) {
1227  *pkt_ok = false; //Don't process any further
1228  return false;
1229  }
1230  if (!ValidateIpPacket(pkt_info)) {
1231  *pkt_ok = false;
1232  return false;
1233  }
1234  return true;
1235 }
1236 
1238  if (pkt_info->agent_hdr.cmd == AgentHdr::TRAP_FLOW_MISS ||
1240  return true;
1241  }
1242  return false;
1243 }
1244 
1245 bool PktHandler::IsFlowPacket(const AgentHdr &agent_hdr) {
1246  if (agent_hdr.cmd == AgentHdr::TRAP_FLOW_MISS ||
1247  agent_hdr.cmd == AgentHdr::TRAP_FLOW_ACTION_HOLD) {
1248  return true;
1249  }
1250  return false;
1251 }
1252 
1254  if (pkt_info->agent_hdr.cmd == AgentHdr::TRAP_ZERO_TTL ||
1256  || pkt_info->agent_hdr.cmd == AgentHdr::TRAP_ROUTER_ALERT)
1257  return true;
1258  return false;
1259 }
1260 
1261 // Check if the packet is destined to the VM's default GW
1262 bool PktHandler::IsGwPacket(const Interface *intf, const IpAddress &dst_ip) {
1263  if (!intf || intf->type() != Interface::VM_INTERFACE)
1264  return false;
1265 
1266  const VmInterface *vm_intf = static_cast<const VmInterface *>(intf);
1267  if (vm_intf->vmi_type() != VmInterface::GATEWAY) {
1268  //Gateway interface doesnt have IP address
1269  if (dst_ip.is_v6() && vm_intf->primary_ip6_addr().is_unspecified())
1270  return false;
1271  else if (dst_ip.is_v4() && vm_intf->primary_ip_addr().is_unspecified())
1272  return false;
1273  }
1274  const VnEntry *vn = vm_intf->vn();
1275  if (vn) {
1276  const std::vector<VnIpam> &ipam = vn->GetVnIpam();
1277  for (unsigned int i = 0; i < ipam.size(); ++i) {
1278  if (dst_ip.is_v4()) {
1279  if (!ipam[i].IsV4()) {
1280  continue;
1281  }
1282  if (ipam[i].default_gw == dst_ip ||
1283  ipam[i].dns_server == dst_ip) {
1284  return true;
1285  }
1286  } else {
1287  if (!ipam[i].IsV6()) {
1288  continue;
1289  }
1290  if (ipam[i].default_gw == dst_ip ||
1291  ipam[i].dns_server == dst_ip) {
1292  return true;
1293  }
1294  }
1295 
1296  }
1297  }
1298 
1299  return false;
1300 }
1301 
1302 bool PktHandler::IsValidInterface(uint32_t ifindex, Interface **intrface) {
1303  Interface *intf = agent_->interface_table()->FindInterface(ifindex);
1304  if (intf == NULL) {
1305  PKT_TRACE(Err, "Invalid interface index <" << ifindex << ">");
1307  return false;
1308  }
1309 
1310  *intrface = intf;
1311  return true;
1312 }
1313 
1315  if (!cb.empty()) {
1316  PktTrace &pkt(pkt_trace_.at(mod));
1317  pkt.Iterate(cb);
1318  }
1319 }
1320 
1322  if (mod < MAX_MODULES)
1323  received[mod]++;
1324 }
1325 
1327  if (mod < MAX_MODULES)
1328  sent[mod]++;
1329 }
1330 
1332  if (mod < MAX_MODULES)
1333  q_threshold_exceeded[mod]++;
1334 }
1335 
1337 
1339  module(PktHandler::INVALID),
1340  pkt(buff->data()), len(buff->data_len()), max_pkt_len(buff->buffer_len()),
1341  data(), ipc(), family(Address::UNSPEC), type(PktType::INVALID), agent_hdr(),
1342  ether_type(-1), ip_saddr(), ip_daddr(), ip_proto(), sport(), dport(),
1343  ttl(0), icmp_chksum(0), tcp_ack(false), tunnel(),
1344  l3_label(false), is_bfd_keepalive(false), is_segment_hc_pkt(false),
1345  ignore_address(VmInterface::IGNORE_NONE), same_port_number(false),
1346  is_fat_flow_src_prefix(false), ip_ff_src_prefix(),
1347  is_fat_flow_dst_prefix(false), ip_ff_dst_prefix(),
1348  eth(), arp(), ip(), ip6(), packet_buffer_(buff) {
1349  transp.tcp = 0;
1350 }
1351 
1352 PktInfo::PktInfo(const PacketBufferPtr &buff, const AgentHdr &hdr) :
1353  pkt(buff->data()), len(buff->data_len()), max_pkt_len(buff->buffer_len()),
1354  data(), ipc(), family(Address::UNSPEC), type(PktType::INVALID),
1355  agent_hdr(hdr), ether_type(-1), ip_saddr(), ip_daddr(), ip_proto(), sport(),
1356  dport(), ttl(0), icmp_chksum(0), tcp_ack(false), tunnel(),
1357  l3_label(false), is_bfd_keepalive(false), is_segment_hc_pkt(false),
1358  ignore_address(VmInterface::IGNORE_NONE), same_port_number(false),
1359  is_fat_flow_src_prefix(false), ip_ff_src_prefix(),
1360  is_fat_flow_dst_prefix(false), ip_ff_dst_prefix(),
1361  eth(), arp(), ip(), ip6(), packet_buffer_(buff) {
1362  transp.tcp = 0;
1363 }
1364 
1365 PktInfo::PktInfo(Agent *agent, uint32_t buff_len, PktHandler::PktModuleName mod,
1366  uint32_t mdata) :
1367  module(mod),
1368  len(), max_pkt_len(), data(), ipc(), family(Address::UNSPEC),
1369  type(PktType::INVALID), agent_hdr(), ether_type(-1), ip_saddr(), ip_daddr(),
1370  ip_proto(), sport(), dport(), ttl(0), icmp_chksum(0), tcp_ack(false),
1371  tunnel(), l3_label(false), is_bfd_keepalive(false), is_segment_hc_pkt(false),
1372  ignore_address(VmInterface::IGNORE_NONE), same_port_number(false),
1373  is_fat_flow_src_prefix(false), ip_ff_src_prefix(),
1374  is_fat_flow_dst_prefix(false), ip_ff_dst_prefix(),
1375  eth(),arp(), ip(), ip6() {
1376 
1378  (module, buff_len, mdata);
1379  pkt = packet_buffer_->data();
1380  len = packet_buffer_->data_len();
1381  max_pkt_len = packet_buffer_->buffer_len();
1382 
1383  transp.tcp = 0;
1384 }
1385 
1387  module(mod),
1388  pkt(), len(), max_pkt_len(0), data(), ipc(msg), family(Address::UNSPEC),
1389  type(PktType::MESSAGE), agent_hdr(), ether_type(-1), ip_saddr(), ip_daddr(),
1390  ip_proto(), sport(), dport(), ttl(0), icmp_chksum(0), tcp_ack(false),
1391  tunnel(), l3_label(false), is_bfd_keepalive(false), is_segment_hc_pkt(false),
1392  ignore_address(VmInterface::IGNORE_NONE), same_port_number(false),
1393  is_fat_flow_src_prefix(false), ip_ff_src_prefix(),
1394  is_fat_flow_dst_prefix(false), ip_ff_dst_prefix(),
1395  eth(), arp(), ip(), ip6(), packet_buffer_() {
1396  transp.tcp = 0;
1397 }
1398 
1400 }
1401 
1403  return agent_hdr;
1404 }
1405 
1407  packet_buffer_.reset();
1408 }
1409 
1410 void PktInfo::AllocPacketBuffer(Agent *agent, uint32_t module, uint16_t len,
1411  uint32_t mdata) {
1413  (module, len, mdata);
1414  pkt = packet_buffer_->data();
1415  len = packet_buffer_->data_len();
1416  max_pkt_len = packet_buffer_->buffer_len();
1417 }
1418 
1419 void PktInfo::set_len(uint32_t x) {
1420  packet_buffer_->set_len(x);
1421  len = x;
1422 }
1423 
1425  eth = (struct ether_header *)(pkt);
1426  ip = (struct ip *)(eth + 1);
1427  transp.tcp = (struct tcphdr *)(ip + 1);
1428 }
1429 
1430 std::size_t PktInfo::hash(const Agent *agent,
1431  const EcmpLoadBalance &ecmp_load_balance) const {
1432  std::size_t seed = 0;
1433  // Bug: 1687879
1434  // Consider that source compute has 2 member ECMP - compute-1 and compute-2
1435  // Compute-1 is chosed in hash is even and Compute-2 is chosen if hash
1436  // is add.
1437  //
1438  // On Compute-1, the hash computation uses same 5-tuple and will always
1439  // result in even number. As a result, flows from Compute-1 will go to
1440  // even-numbered ECMP members and never odd-numbered members.
1441  // If Compute-2 happens to have only 2 members, all flows go to ecmp-index
1442  // 0 and never to 1
1443  //
1444  // Solution:
1445  // We need to ensure that hash computed in Compute-1 and Compute-2 are
1446  // different. We also want to have same hash on agent restarts. So, include
1447  // vhost-ip also to compute hash
1448  if (agent->params()->flow_use_rid_in_hash()) {
1449  boost::hash_combine(seed, agent->router_id().to_ulong());
1450  }
1451 
1452  if (family == Address::INET) {
1453  if (ecmp_load_balance.is_source_ip_set()) {
1454  boost::hash_combine(seed, ip_saddr.to_v4().to_ulong());
1455  }
1456  if (ecmp_load_balance.is_destination_ip_set()) {
1457  boost::hash_combine(seed, ip_daddr.to_v4().to_ulong());
1458  }
1459  } else if (family == Address::INET6) {
1460  if (ecmp_load_balance.is_source_ip_set()) {
1461  uint32_t words[4];
1462  memcpy(words, ip_saddr.to_v6().to_bytes().data(), sizeof(words));
1463  boost::hash_combine(seed, words[0]);
1464  boost::hash_combine(seed, words[1]);
1465  boost::hash_combine(seed, words[2]);
1466  boost::hash_combine(seed, words[3]);
1467  }
1468 
1469  if (ecmp_load_balance.is_destination_ip_set()) {
1470  uint32_t words[4];
1471  memcpy(words, ip_daddr.to_v6().to_bytes().data(), sizeof(words));
1472  boost::hash_combine(seed, words[0]);
1473  boost::hash_combine(seed, words[1]);
1474  boost::hash_combine(seed, words[2]);
1475  boost::hash_combine(seed, words[3]);
1476  }
1477  } else {
1478  assert(0);
1479  }
1480  if (ecmp_load_balance.is_ip_protocol_set()) {
1481  boost::hash_combine(seed, ip_proto);
1482  }
1483  if (ecmp_load_balance.is_source_port_set()) {
1484  boost::hash_combine(seed, sport);
1485  }
1486  if (ecmp_load_balance.is_destination_port_set()) {
1487  boost::hash_combine(seed, dport);
1488  }
1489 
1490  // When only the sport changes by 2, its observed that only the lower 32
1491  // bits of hash changes. Just hash combine upper and lower 32 bit numbers
1492  // to randomize in case of incremental sport numbers
1493  std::size_t hash = 0;
1494  boost::hash_combine(hash, (seed & 0xFFFFFFFF));
1495  boost::hash_combine(hash, (seed >> 16));
1496  return hash;
1497 }
1498 
1500  if (ip_proto == IPPROTO_UDP) {
1501  return ntohs(transp.udp->uh_ulen) - sizeof(udphdr);
1502  }
1503  return 0;
1504 }
1505 
1507  const PktInfo *pkt) {
1508  pkt_trace_.at(module).AddPktTrace(PktTrace::In, pkt->len, pkt->pkt,
1509  &pkt->agent_hdr);
1510 }
1511 
1513  boost::shared_ptr<PktInfo> pkt_info) {
1514  if (!(proto_list_.at(module)->Enqueue(pkt_info))) {
1515  stats_.PktQThresholdExceeded(module);
1516  }
1517  return;
1518 }
1519 
1521 void PktTrace::Pkt::Copy(Direction d, std::size_t l, uint8_t *msg,
1522  std::size_t pkt_trace_size, const AgentHdr *hdr) {
1523  uint16_t hdr_len = sizeof(AgentHdr);
1524  dir = d;
1525  len = l + hdr_len;
1526  memcpy(pkt, hdr, hdr_len);
1527  memcpy(pkt + hdr_len, msg, std::min(l, (pkt_trace_size - hdr_len)));
1528 }
1529 
1530 void PktTrace::AddPktTrace(Direction dir, std::size_t len, uint8_t *msg,
1531  const AgentHdr *hdr) {
1532  if (num_buffers_) {
1533  end_ = (end_ + 1) % num_buffers_;
1534  pkt_buffer_[end_].Copy(dir, len, msg, pkt_trace_size_, hdr);
1535  count_ = std::min((count_ + 1), (uint32_t) num_buffers_);
1536  }
1537 }
bool MeasureQueueDelay()
Definition: agent.cc:1136
Direction dir
Definition: pkt_trace.h:25
uint32_t dport
Definition: pkt_handler.h:398
std::size_t len
Definition: pkt_trace.h:26
IpAddress ip_saddr
Definition: pkt_handler.h:394
boost::function< void(PktTrace::Pkt &)> PktTraceCallback
Definition: pkt_handler.h:227
bool IsSegmentHealthCheckPacket(const PktInfo *pkt_info, const Interface *interface)
Definition: pkt_handler.cc:232
const Interface * GetInterface() const
Definition: nexthop.h:1293
int ParseVxlan(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:880
void AllocPacketBuffer(Agent *agent, uint32_t module, uint16_t len, uint32_t mdata)
Address::Family family
Definition: pkt_handler.h:386
#define DHCP_SERVER_PORT
Definition: pkt_handler.h:29
boost::shared_ptr< PacketBuffer > PacketBufferPtr
Definition: packet_buffer.h:18
bool is_source_port_set() const
bool is_fat_flow_src_prefix
Definition: pkt_handler.h:414
void Enqueue(PktModuleName module, boost::shared_ptr< PktInfo > pkt_info)
int ParseEthernetHeader(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:528
const Interface * GetFirstLocalEcmpMemberInterface() const
Definition: nexthop.cc:1837
Type type() const
Definition: interface.h:112
MacAddress b_smac
Definition: pkt_handler.h:402
void incr_pkt_invalid_ip_pkt()
Definition: agent_stats.h:146
#define BFD_ECHO_PORT
Definition: pkt_handler.h:34
uint32_t ifindex
Definition: pkt_handler.h:180
void SendMessage(PktModuleName mod, InterTaskMsg *msg)
bool is_destination_ip_set() const
static Agent * GetInstance()
Definition: agent.h:436
uint16_t max_pkt_len
Definition: pkt_handler.h:381
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
Definition: vrf.h:86
NextHop * FindNextHop(size_t index)
Definition: nexthop.cc:3447
struct ip * ip
Definition: pkt_handler.h:423
union PktInfo::@8 transp
void Shutdown(bool delete_entries=true)
Definition: queue_task.h:152
#define PKT_TRACE(obj, arg)
Definition: pkt_handler.cc:35
void SetOuterIp(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:513
const uint32_t id() const
Definition: interface.h:123
NextHopTable * nexthop_table() const
Definition: agent.h:475
void SetType(TunnelType::Type type)
Definition: nexthop.h:304
static const uint32_t kMulticastControlWord
Definition: pkt_handler.h:229
#define DHCPV6_SERVER_PORT
Definition: pkt_handler.h:31
void incr_pkt_exceptions()
Definition: agent_stats.h:128
uint32_t ip_daddr
Definition: pkt_handler.h:216
uint8_t ip_proto
Definition: pkt_handler.h:396
PktHandler::PktModuleName module
Definition: pkt_handler.h:378
const Interface * vhost_interface() const
Definition: agent.h:935
int ParseUserPkt(PktInfo *pkt_info, Interface *intf, PktType::Type &pkt_type, uint8_t *pkt)
Definition: pkt_handler.cc:919
const NextHop * nexthop() const
Definition: mpls.h:80
bool dns_enabled() const
Definition: interface.h:126
uint32_t vxlan_id
Definition: pkt_handler.h:92
boost::asio::ip::address IpAddress
Definition: address.h:13
static const MacAddress & vrrp_mac()
Definition: agent.h:439
Type GetType() const
Definition: nexthop.h:303
uint8_t * data
Definition: pkt_handler.h:383
struct ether_header * eth
Definition: pkt_handler.h:217
bool layer2_control_word() const
Definition: nexthop.h:1918
AgentStats * stats() const
Definition: agent.cc:881
IpAddress ip_ff_src_prefix
Definition: pkt_handler.h:415
static const std::string kDiagData
Definition: diag.h:107
uint32_t label
Definition: pkt_handler.h:212
#define IANA_MPLS_OVER_UDP_DEST_PORT
Definition: pkt_handler.h:37
PktInfo(Agent *agent, uint32_t buff_len, PktHandler::PktModuleName module, uint32_t mdata)
void set_len(uint32_t len)
MacAddress dmac
Definition: pkt_handler.h:393
uint32_t ip_saddr
Definition: pkt_handler.h:215
bool IsToRDevice(uint32_t vrf_id, const IpAddress &ip)
void UpdateHeaderPtr()
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
void PktSent(PktModuleName mod)
InterfaceTable * interface_table() const
Definition: agent.h:465
const Ip4Address * GetDip() const
Definition: tunnel_nh.h:37
void PktRcvd(PktModuleName mod)
uint16_t protocol
Definition: pkt_handler.h:76
char data_[8]
Definition: diag.h:85
#define BFD_SINGLEHOP_CONTROL_PORT
Definition: pkt_handler.h:33
bool layer2_control_word() const
Definition: nexthop.h:1359
struct ether_header * eth
Definition: pkt_handler.h:420
ControlInterface * control_interface() const
Definition: pkt_init.h:46
bool IsBridge() const
Definition: nexthop.h:1299
const MacAddress & mac() const
Definition: interface.h:131
uint32_t count_
Definition: pkt_trace.h:78
void Register(PktModuleName type, RcvQueueFunc cb)
struct icmp6_hdr * icmp6
Definition: pkt_handler.h:429
bool ProcessBfdDataPacket(boost::shared_ptr< PacketBufferEnqueueItem > item)
Definition: pkt_handler.cc:442
MplsTable * mpls_table() const
Definition: agent.h:510
const VmInterface * FindVmFromDhcpBinding(const MacAddress &mac)
bool IsTunnelEnabled() const
Definition: interface.h:109
bool l3_label
Definition: pkt_handler.h:408
Type GetType() const
Definition: nexthop.h:405
uint64_t pkt_drop_due_to_flow_trap() const
Definition: agent_stats.h:162
void AddPktTrace(PktModuleName module, PktTrace::Direction dir, const PktInfo *pkt)
PacketBufferPtr packet_buffer_
Definition: pkt_handler.h:456
PktHandlerQueue work_queue_
Definition: pkt_handler.h:371
void incr_pkt_dropped()
Definition: agent_stats.h:164
Agent * agent() const
Definition: pkt_handler.h:317
uint32_t sport
Definition: pkt_handler.h:397
void AddPktTrace(Direction dir, std::size_t len, uint8_t *msg, const AgentHdr *hdr)
std::vector< Pkt > pkt_buffer_
Definition: pkt_trace.h:81
bool flow_use_rid_in_hash() const
Definition: agent_param.h:434
PktStats stats_
Definition: pkt_handler.h:365
TunnelInfo tunnel
Definition: pkt_handler.h:407
bool IsDHCPPacket(PktInfo *pkt_info)
std::size_t pkt_trace_size_
Definition: pkt_trace.h:80
virtual bool Enqueue(boost::shared_ptr< PktInfo > msg)
int ParseMplsHdr(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:777
u_int16_t th_sport
Definition: pkt_handler.h:122
#define VLAN_HDR_LEN
Definition: pkt_handler.h:49
uint32_t hdr
Definition: pkt_handler.h:83
void SetOuterMac(PktInfo *pkt_info)
Definition: pkt_handler.cc:523
Agent * agent_
Definition: pkt_handler.h:369
BridgeRouteEntry * FindRoute(const MacAddress &mac)
Definition: bridge_route.cc:72
virtual ~PktInfo()
VrfEntry * FindVrfFromId(size_t index)
Definition: vrf.cc:884
#define VXLAN_UDP_DEST_PORT
Definition: pkt_handler.h:36
uint16_t ether_type
Definition: pkt_handler.h:389
uint8_t type
Definition: load_balance.h:109
bool dhcp_enabled_v6() const
Definition: interface.h:125
bool IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, PktType::Type &pkt_type, uint8_t *pkt, bool *pkt_ok)
Definition: agent.h:358
PktHandler(Agent *, PktModule *pkt_module)
Definition: pkt_handler.cc:57
uint32_t vrf_id() const
Definition: interface.cc:621
void incr_pkt_drop_due_to_decode_error()
Definition: agent_stats.h:155
uint16_t len
Definition: pkt_handler.h:380
struct udphdr * udp
Definition: pkt_handler.h:427
virtual ~PktHandler()
Definition: pkt_handler.cc:78
uint32_t ttl
Definition: pkt_handler.h:399
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:881
IpAddress ip_ff_dst_prefix
Definition: pkt_handler.h:417
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
Ip4Address router_id() const
Definition: agent.h:666
uint8_t * pkt
Definition: pkt_handler.h:379
bool IsBFDHealthCheckPacket(const PktInfo *pkt_info, const Interface *interface)
Definition: pkt_handler.cc:219
static const uint32_t kMulticastControlWordSize
Definition: pkt_handler.h:230
bool tcp_ack
Definition: pkt_handler.h:406
int ParseMPLSoGRE(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:838
TunnelType type
Definition: pkt_handler.h:211
struct ether_arp * arp
Definition: pkt_handler.h:422
static const std::size_t kPktMaxTraceSize
Definition: pkt_trace.h:14
void Iterate(Cb cb)
Definition: pkt_trace.h:49
bool dhcp_enabled() const
Definition: interface.h:124
bool IsGwPacket(const Interface *intf, const IpAddress &dst_ip)
void incr_pkt_drop_due_to_disable_tnl()
Definition: agent_stats.h:149
uint32_t vrf
Definition: pkt_handler.h:181
static bool ComputeDirection(const Interface *intf)
#define ETHERTYPE_QINQ
Definition: pkt_handler.h:53
AgentRouteTable * GetBridgeRouteTable() const
Definition: vrf.cc:334
bool bridge_nh() const
Definition: nexthop.h:1448
void set_measure_busy_time(bool val) const
Definition: queue_task.h:379
bool IsValidInterface(uint32_t ifindex, Interface **interface)
void PktTraceIterate(PktModuleName mod, PktTraceCallback cb)
std::size_t num_buffers_
Definition: pkt_trace.h:79
#define BFD_MULTIHOP_CONTROL_PORT
Definition: pkt_handler.h:35
bool IsDiagPacket(PktInfo *pkt_info)
const std::vector< VnIpam > & GetVnIpam() const
Definition: vn.h:171
static const MacAddress & BroadcastMac()
Definition: mac_address.h:152
const VnEntry * vn() const
bool is_source_ip_set() const
void Send(const AgentHdr &hdr, const PacketBufferPtr &buff)
Definition: pkt_handler.cc:94
bool init_done() const
Definition: agent.h:1213
bool ProcessPacket(boost::shared_ptr< PacketBufferEnqueueItem > item)
Definition: pkt_handler.cc:426
PktModuleName ParsePacket(const AgentHdr &hdr, PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:280
COMPOSITETYPE composite_nh_type() const
Definition: nexthop.h:1842
uint32_t nh
Definition: pkt_handler.h:189
AgentParam * params() const
Definition: agent.h:1218
uint32_t vrf
Definition: pkt_handler.h:391
bool ExcludeFromFatFlow(Address::Family family, const IpAddress &sip, const IpAddress &dip) const
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
bool ValidateIpPacket(PktInfo *pkt_info)
Definition: pkt_handler.cc:903
Definition: vn.h:151
static const uint32_t kInvalidLabel
Definition: mpls.h:101
void incr_pkt_fragments_dropped()
Definition: agent_stats.h:140
#define DNS_SERVER_PORT
Definition: bind_util.h:28
const FatFlowList & fat_flow_list() const
VrfTable * vrf_table() const
Definition: agent.h:485
std::string AgentBackTrace(int skip=1)
Definition: agent.cc:1187
ComponentNHList::const_iterator begin() const
Definition: nexthop.h:1807
const Ip4Address & primary_ip_addr() const
uint32_t * pbb_header
Definition: pkt_handler.h:421
uint32_t GetUdpPayloadLength() const
#define ETHERTYPE_PBB
Definition: pkt_handler.h:54
const AgentHdr & GetAgentHdr() const
virtual int Send(const AgentHdr &hdr, const PacketBufferPtr &pkt)=0
int ParseMPLSoUDP(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:866
void incr_pkt_invalid_frm_tor()
Definition: agent_stats.h:152
void incr_pkt_invalid_interface()
Definition: agent_stats.h:134
void reset_packet_buffer()
bool IgnoreFragmentedPacket(PktInfo *pkt_info)
PacketBufferManager * packet_buffer_manager() const
Definition: pkt_init.h:33
struct tcphdr * tcp
Definition: pkt_handler.h:426
VmInterface::VmiType vmi_type() const
struct ip6_hdr * ip6
Definition: pkt_handler.h:424
void CalculatePortIP(PktInfo *pkt_info)
Definition: pkt_handler.cc:104
const Ip6Address & primary_ip6_addr() const
Definition: mpls.h:52
struct icmp * icmp
Definition: pkt_handler.h:428
bool is_segment_hc_pkt
Definition: pkt_handler.h:411
bool same_port_number
Definition: pkt_handler.h:413
PacketBufferPtr Allocate(uint32_t module, uint16_t len, uint32_t mdata)
virtual uint32_t EncapsulationLength() const =0
bool IsFabricMulticastReservedLabel() const
Definition: mpls.cc:135
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
MacAddress smac
Definition: pkt_handler.h:392
#define LOG(_Level, _Msg)
Definition: logging.h:33
uint32_t i_sid
Definition: pkt_handler.h:404
struct igmp * igmp
Definition: pkt_handler.h:431
PktModuleName ParseBfdDataPacket(const AgentHdr &hdr, PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:245
MacAddress b_dmac
Definition: pkt_handler.h:403
bool layer2_control_word() const
Definition: nexthop.h:1461
bool IsFatFlowPrefixAggregation(bool ingress, uint8_t protocol, uint16_t *sport, uint16_t *dport, bool *same_port_num, IpAddress *SrcIP, IpAddress *DstIP, bool *is_src_prefix, bool *is_dst_prefix, FatFlowIgnoreAddressType *ignore_addr) const
void PktQThresholdExceeded(PktModuleName mod)
Proto * bfd_keepalive_proto_
Definition: pkt_handler.h:363
bool IsFatFlowPortBased(uint8_t protocol, uint16_t port, FatFlowIgnoreAddressType *ignore_addr) const
boost::array< Proto *, MAX_MODULES > proto_list_
Definition: pkt_handler.h:362
IpAddress ip_daddr
Definition: pkt_handler.h:395
uint32_t cmd_param
Definition: pkt_handler.h:183
void incr_pkt_drop_due_to_invalid_ethertype()
Definition: agent_stats.h:158
uint8_t pkt[kPktMaxTraceSize]
Definition: pkt_trace.h:27
AgentHdr agent_hdr
Definition: pkt_handler.h:388
uint32_t end_
Definition: pkt_trace.h:77
boost::array< PktTrace, MAX_MODULES > pkt_trace_
Definition: pkt_handler.h:366
uint16_t cmd
Definition: pkt_handler.h:182
bool is_fat_flow_dst_prefix
Definition: pkt_handler.h:416
uint32_t EncapHeaderLen() const
Definition: pkt_handler.cc:89
ComponentNHList::const_iterator end() const
Definition: nexthop.h:1811
int ParseControlWord(PktInfo *pkt_info, uint8_t *pkt, const MplsLabel *mpls)
Definition: pkt_handler.cc:736
VmInterface::FatFlowIgnoreAddressType ignore_address
Definition: pkt_handler.h:412
PktModule * pkt() const
Definition: agent.cc:965
void PktModuleEnqueue(PktModuleName mod, const AgentHdr &hdr, boost::shared_ptr< PktInfo > pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:472
PktHandlerQueue work_queue_bfd_ka_
Definition: pkt_handler.h:372
u_int16_t th_dport
Definition: pkt_handler.h:123
bool is_destination_port_set() const
bool ComputeForwardingMode(PktInfo *pkt_info, const Interface *intf) const
Definition: pkt_handler.cc:490
const Interface * GetInterface() const
Definition: nexthop.h:1543
#define PBB_HEADER_LEN
Definition: pkt_handler.h:55
bool Enqueue(QueueEntryT entry)
Definition: queue_task.h:248
void Copy(Direction d, std::size_t l, uint8_t *msg, std::size_t pkt_trace_size, const AgentHdr *hdr)
std::size_t hash(const Agent *agent, const EcmpLoadBalance &ecmp_has_fields_to_use) const
uint16_t icmp_chksum
Definition: pkt_handler.h:400
uint32_t vxlan_id
Definition: pkt_handler.h:213
bool IsFlowPacket(PktInfo *pkt_info)
#define MPLS_OVER_UDP_DEST_PORT
Definition: pkt_handler.h:38
int ParseUDPTunnels(PktInfo *pkt_info, uint8_t *pkt)
Definition: pkt_handler.cc:892
void set_name(const std::string &name)
Definition: queue_task.h:307
bool is_ip_protocol_set() const
void HandleRcvPkt(const AgentHdr &hdr, const PacketBufferPtr &buff)
Definition: pkt_handler.cc:411
#define DHCP_CLIENT_PORT
Definition: pkt_handler.h:30
int ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type, uint8_t *ptr)
Definition: pkt_handler.cc:555
struct ip * ip
Definition: pkt_handler.h:218
struct sctphdr * sctp
Definition: pkt_handler.h:430
uint32_t received[MAX_MODULES]
Definition: pkt_handler.h:253
#define DHCPV6_CLIENT_PORT
Definition: pkt_handler.h:32