22 #include <netinet/icmp6.h>
25 using namespace boost::posix_time;
34 proto = pkt_info_->ip->ip_p;
36 proto = pkt_info_->ip6->ip6_nxt;
40 pkt_info_->transp.tcp->th_sum = 0xffff;
44 pkt_info_->transp.udp->uh_sum = 0xffff;
48 pkt_info_->transp.icmp->icmp_cksum = 0xffff;
51 pkt_info_->transp.icmp6->icmp6_cksum = 0xffff;
72 diag_table_->diag_proto()->IncrementDiagStats(GetInterfaceIndex(),
77 diag_table_->diag_proto()->IncrementDiagStats(GetInterfaceIndex(),
99 if (pkt_info_->ether_type == ETHERTYPE_IP) {
100 ttl = pkt_info_->ip->ip_ttl;
101 }
else if (pkt_info_->ether_type == ETHERTYPE_IPV6) {
102 ttl = pkt_info_->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
114 SendOverlayResponse();
116 if (pkt_info_->ether_type == ETHERTYPE_IP) {
117 SendTimeExceededPacket();
119 SendTimeExceededV6Packet();
124 return HandleTraceRouteResponse();
130 uint16_t icmp_len = pkt_info_->ip->ip_hl * 4 + 128;
131 if (ntohs(pkt_info_->ip->ip_len) < icmp_len)
132 icmp_len = ntohs(pkt_info_->ip->ip_len);
133 boost::scoped_array<uint8_t> icmp_payload(
new uint8_t[icmp_len]);
134 memcpy(icmp_payload.get(), pkt_info_->ip, icmp_len);
136 if (!ParseIcmpData(icmp_payload.get(), icmp_len, (uint16_t *)&key,
true))
139 char *ptr = (
char *)pkt_info_->pkt;
140 uint16_t buf_len = pkt_info_->max_pkt_len;
143 uint16_t len = (
char *)pkt_info_->eth - (
char *)pkt_info_->pkt;
147 (agent()->interface_table()->FindInterface(GetInterfaceIndex()));
148 if (vm_itf == NULL) {
149 src_ip = agent()->router_id();
151 if (vm_itf->
vn() == NULL) {
154 const VnIpam *ipam = vm_itf->
vn()->
GetIpam(pkt_info_->ip_saddr.to_v4());
162 len += EthHdr(ptr + len, buf_len - len, agent()->vhost_interface()->mac(),
163 MacAddress(pkt_info_->eth->ether_shost), ETHERTYPE_IP,
166 uint16_t ip_len =
sizeof(iphdr) + 8 + icmp_len;
167 len += IpHdr(ptr + len, buf_len - len, ip_len,
168 htonl(src_ip.to_ulong()),
169 htonl(pkt_info_->ip_saddr.to_v4().to_ulong()),
172 struct icmp *hdr = (
struct icmp *) (ptr + len);
173 memset((uint8_t *)hdr, 0, 8);
174 hdr->icmp_type = ICMP_TIME_EXCEEDED;
175 hdr->icmp_code = ICMP_EXC_TTL;
176 memcpy(ptr + len + 8, icmp_payload.get(), icmp_len);
177 IcmpChecksum((
char *)hdr, 8 + icmp_len);
180 pkt_info_->set_len(len);
188 uint8_t icmp_payload[icmp_payload_len];
189 uint16_t icmp_len = ntohs(pkt_info_->ip6->ip6_plen);
191 if (icmp_len > icmp_payload_len)
192 icmp_len = icmp_payload_len;
193 memcpy(icmp_payload, pkt_info_->ip6, icmp_len);
196 if (!ParseIcmpData(icmp_payload, icmp_len, (uint16_t *)&key,
false))
199 char *buff = (
char *)pkt_info_->pkt;
200 uint16_t buff_len = pkt_info_->max_pkt_len;
203 uint16_t eth_len = EthHdr(buff, buff_len, GetInterfaceIndex(),
204 agent()->vhost_interface()->mac(),
209 (agent()->interface_table()->FindInterface(GetInterfaceIndex()));
211 vm_itf->
vn() == NULL) {
215 const VnIpam *ipam = vm_itf->
vn()->
GetIpam(pkt_info_->ip_saddr.to_v6());
219 pkt_info_->ip6 = (
struct ip6_hdr *)(buff + eth_len);
222 pkt_info_->ip_saddr.to_v6().to_bytes().data());
224 icmp6_hdr *icmp = pkt_info_->transp.icmp6 =
225 (icmp6_hdr *)(pkt_info_->pkt + eth_len
227 icmp->icmp6_type = ICMP_TIME_EXCEEDED;
228 icmp->icmp6_code = ICMP_EXC_TTL;
230 icmp->icmp6_cksum = 0;
232 Icmpv6Csum(ipam->
default_gw.to_v6().to_bytes().data(),
233 pkt_info_->ip_saddr.to_v6().to_bytes().data(),
236 icmp_payload, icmp_len);
243 Send(GetInterfaceIndex(), pkt_info_->vrf, command,
249 uint8_t *data = (uint8_t *)(pkt_info_->transp.icmp) + 8;
250 uint16_t len = pkt_info_->len - (data - pkt_info_->pkt);
251 bool is_v4 = pkt_info_->ether_type == ETHERTYPE_IP;
254 if (IsOverlayPingPacket()) {
258 if (!ParseIcmpData(data, len, (uint16_t *)&key, is_v4))
262 DiagEntry *entry = diag_table_->Find(key);
263 if (!entry)
return true;
266 address_ = pkt_info_->ip_saddr.to_v4().to_string();
268 address_ = pkt_info_->ip_saddr.to_v6().to_string();
284 uint16_t *key,
bool is_v4) {
285 if (data_len <
sizeof(
struct ip))
287 struct ip *ip_hdr = (
struct ip *)(data);
288 *key = ntohs(ip_hdr->ip_id);
289 uint16_t len =
sizeof(
struct ip);
292 if (ip_hdr->ip_src.s_addr == htonl(agent()->router_id().to_ulong()) ||
293 ip_hdr->ip_dst.s_addr == htonl(agent()->router_id().to_ulong())) {
295 switch (ip_hdr->ip_p) {
297 if (data_len < len +
sizeof(
GreHdr))
304 if (data_len < len +
sizeof(udphdr))
306 len +=
sizeof(udphdr);
316 if (data_len < len +
sizeof(
struct ip))
318 ip_hdr = (
struct ip *)(data + len);
319 len +=
sizeof(
struct ip);
320 protocol = ip_hdr->ip_p;
322 if (data_len < len +
sizeof(
struct ip6_hdr))
324 struct ip6_hdr *ip6_hdr = (
struct ip6_hdr *)(data + len);
325 len +=
sizeof(
struct ip6_hdr);
326 protocol = ip6_hdr->ip6_nxt;
330 len +=
sizeof(tcphdr);
334 len +=
sizeof(udphdr);
353 *key = ntohs(agent_data->
key_);
362 bool isoverlay_packet = IsOverlayPingPacket();
366 if (IsTraceRoutePacket()) {
367 return HandleTraceRoutePacket();
370 if (isoverlay_packet) {
394 DiagEntry *entry = diag_table_->Find(key);
401 if (isoverlay_packet) {
403 SendOverlayResponse();
406 if (segment_hc_pkt) {
407 SegmentHealthCheckReply();
423 if (segment_hc_pkt) {
440 uint16_t dport,
bool is_syn, uint32_t seq_no,
442 struct tcphdr *tcp = pkt_info_->transp.tcp;
443 tcp->th_sport = htons(sport);
444 tcp->th_dport = htons(dport);
447 tcp->th_flags &= ~TH_ACK;
450 tcp->th_flags &= ~TH_SYN;
453 tcp->th_seq = htons(seq_no);
454 tcp->th_ack = htons(seq_no + 1);
456 tcp->th_win = htons(1000);
459 tcp->th_sum = TcpCsum(src, dst, len, tcp);
463 const uint8_t *dest, uint16_t dport,
bool is_syn,
464 uint32_t seq_no, uint8_t next_hdr){
465 struct tcphdr *tcp = pkt_info_->transp.tcp;
466 tcp->th_sport = htons(sport);
467 tcp->th_dport = htons(dport);
470 tcp->th_flags &= ~TH_ACK;
473 tcp->th_flags &= ~TH_SYN;
476 tcp->th_seq = htons(seq_no);
477 tcp->th_ack = htons(seq_no + 1);
479 tcp->th_win = htons(1000);
482 tcp->th_sum = Ipv6Csum(src, dest, len, next_hdr, (uint16_t *)tcp);
489 sum = Sum((uint16_t *)&phdr,
sizeof(
PseudoTcpHdr), sum);
490 return Csum((uint16_t *)tcp, len, sum);
494 if (pkt_info_->ip_proto == IPPROTO_TCP) {
495 tcphdr *tcp = pkt_info_->transp.tcp;
496 TcpHdr(htonl(pkt_info_->ip_daddr.to_v4().to_ulong()),
497 ntohs(tcp->th_dport),
498 htonl(pkt_info_->ip_saddr.to_v4().to_ulong()),
499 ntohs(tcp->th_sport),
false, ntohs(tcp->th_ack),
500 ntohs(pkt_info_->ip->ip_len) -
sizeof(
struct ip));
501 }
else if (pkt_info_->ip_proto == IPPROTO_UDP) {
502 udphdr *udp = pkt_info_->transp.udp;
503 UdpHdr(ntohs(udp->uh_ulen), pkt_info_->ip_daddr.to_v4().to_ulong(),
504 ntohs(udp->uh_dport), pkt_info_->ip_saddr.to_v4().to_ulong(),
505 ntohs(udp->uh_sport));
506 }
else if (pkt_info_->ip_proto == IPPROTO_ICMP) {
507 struct icmp *hdr = (
struct icmp *) (pkt_info_->transp.icmp);
508 if (hdr->icmp_type == ICMP_ECHO) {
509 hdr->icmp_type = ICMP_ECHOREPLY;
517 if (pkt_info_->ip_proto == IPPROTO_TCP) {
518 tcphdr *tcp = pkt_info_->transp.tcp;
519 TcpHdr(ntohs(pkt_info_->ip6->ip6_ctlun.ip6_un1.ip6_un1_plen) -
sizeof(
struct ip6_hdr),
520 pkt_info_->ip_daddr.to_v6().to_bytes().data(), ntohs(tcp->th_dport),
521 pkt_info_->ip_saddr.to_v6().to_bytes().data(), ntohs(tcp->th_sport),
522 false, ntohs(tcp->th_ack), IPPROTO_TCP);
523 }
else if (pkt_info_->ip_proto == IPPROTO_UDP) {
524 udphdr *udp = pkt_info_->transp.udp;
525 UdpHdr(ntohs(udp->uh_ulen), pkt_info_->ip_daddr.to_v6().to_bytes().data(),
526 ntohs(udp->uh_dport), pkt_info_->ip_saddr.to_v6().to_bytes().data(),
527 ntohs(udp->uh_sport), IPPROTO_UDP);
533 struct ip *ip = pkt_info_->ip;
534 IpHdr(ntohs(ip->ip_len), ip->ip_dst.s_addr,
540 struct ip6_hdr *ip6 = pkt_info_->ip6;
541 Ip6Hdr(ip6, ntohl(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen),
543 pkt_info_->ip_daddr.to_v6().to_bytes().data(),
544 pkt_info_->ip_saddr.to_v6().to_bytes().data());
548 struct ether_header *eth = pkt_info_->eth;
553 if (pkt_info_->ether_type == ETHERTYPE_IPV6) {
592 while (tlv_length - parsed_tlv >= (
int)
sizeof(
SubTlv)) {
594 parsed_tlv +=
sizeof(
SubTlv);
596 const int subtlv_length = ntohs(subtlv->
length_);
598 parsed_tlv += subtlv_length;
602 int parsed_subtlv = 0;
604 while (subtlv_length - parsed_subtlv >=
622 parsed_tlv += subtlv_length;
627 struct ether_header *eth = pkt_info_->tunnel.eth;
628 EthHdr((
char *)eth,
sizeof(
struct ether_header),
MacAddress(eth->ether_dhost),
629 MacAddress(eth->ether_shost), ntohs(eth->ether_type),
631 struct ip *ip = pkt_info_->tunnel.ip;
632 IpHdr((
char *)ip,
sizeof(
struct ip), ntohs(ip->ip_len),ip->ip_dst.s_addr,
645 SetReturnCode(oamdata);
648 boost::posix_time::ptime
649 epoch(boost::gregorian::date(1970, boost::gregorian::Jan, 1));
650 boost::posix_time::ptime time = microsec_clock::universal_time();
651 boost::posix_time::time_duration td = time - epoch;
654 (td.total_seconds()*1000000));
uint32_t GetMaxAttempts()
void SendTimeExceededV6Packet()
static Agent * GetInstance()
VrfEntry * fabric_vrf() const
void SendOverlayResponse()
static const uint32_t kVxlanRABit
const VrfEntry * GetVrf() const
const VnIpam * GetIpam(const IpAddress &ip) const
InterfaceTable * interface_table() const
BridgeRouteEntry * FindRoute(const MacAddress &mac)
#define VXLAN_UDP_DEST_PORT
void SendTimeExceededPacket()
static const uint32_t kInvalidVlanId
const std::string & fabric_interface_name() const
void SegmentHealthCheckReply()
bool layer3_forwarding() const
AgentRouteTable * GetBridgeRouteTable() const
uint16_t TcpCsum(in_addr_t, in_addr_t, uint16_t, tcphdr *)
virtual void HandleReply(DiagPktHandler *handler)=0
const VnEntry * vn() const
AgentDBEntry * Find(const DBEntry *key, bool ret_del)
const uint32_t vrf_id() const
void TcpHdr(in_addr_t, uint16_t, in_addr_t, uint16_t, bool, uint32_t, uint16_t)
DiagTable * diag_table() const
boost::asio::ip::address_v4 Ip4Address
const NextHop * nexthop() const
void SetReturnCode(OverlayOamPktData *oamdata)
bool IsOverlayPingPacket()
bool HandleTraceRoutePacket()
#define ICMP_UNREACH_HDR_LEN
VxLanId * Find(uint32_t vxlan_id)
VxLanTable * vxlan_table() const
bool ParseIcmpData(const uint8_t *data, uint16_t data_len, uint16_t *key, bool is_v4)
bool HandleTraceRouteResponse()
bool IsTraceRoutePacket()
void Enqueue(DiagEntryOp *op)
#define IPV6_ICMP_NEXT_HEADER