From 2789e04d0eb336e25e4e69ef61701af320249bcd Mon Sep 17 00:00:00 2001 From: Naveen N Date: Fri, 26 Feb 2016 14:22:43 +0530 Subject: [PATCH] * In case of IPv6 ICMP errors parse thru inner payload and frame the flow key. Closes-bug:#1542207 Change-Id: I66793922b0bba02c43c9eebde86bafa7e8035e9e Fix Agent UT failures Fix failures in test_pkt_flowv6 and test_sg_flowv6 For ICMPv6 protocol set the ICMP type as ECHO_REQUEST and lookup of ICMPv6 flows should be done with destination port as ECHO_REPLY (cherry picked from commit 4e6f8c92e80ab0a69dcd8ef710a77fbf7372d152) Closes-Bug: #1550727 Change-Id: I89c2137fcaac812bcfb517c7c3aa531b2fed5421 --- src/vnsw/agent/pkt/pkt_handler.cc | 15 +++++++++++++ src/vnsw/agent/pkt/test/test_flow_util.h | 26 ++++++++++------------- src/vnsw/agent/pkt/test/test_pkt_util.cc | 4 ++-- src/vnsw/agent/pkt/test/test_sg_flowv6.cc | 6 +++++- src/vnsw/agent/test/pkt_gen.h | 8 +++++++ src/vnsw/agent/test/test_util.cc | 3 +++ 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index 1d2f801a42e..79e42767bc6 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -454,6 +454,21 @@ int PktHandler::ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type, icmp->icmp6_type == ICMP6_ECHO_REPLY) { pkt_info->dport = ICMP6_ECHO_REPLY; pkt_info->sport = htons(icmp->icmp6_id); + } else if (IsFlowPacket(pkt_info) && + icmp->icmp6_type < ICMP6_ECHO_REQUEST) { + //Agent has to look at inner payload + //and recalculate the parameter + //Handle this only for packets requiring flow miss + ParseIpPacket(pkt_info, pkt_type, pkt + len + sizeof(icmp)); + //Swap the key parameter, which would be used as key + IpAddress src_ip = pkt_info->ip_saddr; + pkt_info->ip_saddr = pkt_info->ip_daddr; + pkt_info->ip_daddr = src_ip; + if (pkt_info->ip_proto != IPPROTO_ICMPV6) { + uint16_t port = pkt_info->sport; + pkt_info->sport = pkt_info->dport; + pkt_info->dport = port; + } } else { pkt_info->sport = 0; } diff --git a/src/vnsw/agent/pkt/test/test_flow_util.h b/src/vnsw/agent/pkt/test/test_flow_util.h index 71194f89250..91cd7d87c6d 100644 --- a/src/vnsw/agent/pkt/test/test_flow_util.h +++ b/src/vnsw/agent/pkt/test/test_flow_util.h @@ -178,7 +178,7 @@ class TestFlowPkt { }; bool FlowStatus(bool active) { - FlowEntry *fe = FlowGet(vrf_, sip_, dip_, proto_, sport_, dport_, nh_id_); + FlowEntry * fe = FlowFetch(); if (fe == NULL || fe->deleted()) { return !active; } @@ -201,35 +201,31 @@ class TestFlowPkt { WAIT_FOR(1000, 3000, FlowStatus(true)); //Get flow - FlowEntry *fe = FlowGet(vrf_, sip_, dip_, proto_, sport_, dport_, - nh_id_); + FlowEntry * fe = FlowFetch(); EXPECT_TRUE(fe != NULL); return fe; }; void Delete() { - FlowKey key; - key.nh = nh_id_; - key.src_addr = IpAddress::from_string(sip_); - key.dst_addr = IpAddress::from_string(dip_); - key.src_port = sport_; - key.dst_port = dport_; - key.protocol = proto_; - key.family = Address::INET; - - if (Agent::GetInstance()->pkt()->get_flow_proto()->Find(key) == NULL) { + FlowEntry * fe = FlowFetch(); + if (fe == NULL) { return; } TaskScheduler *scheduler = TaskScheduler::GetInstance(); - FlowDeleteTask * task = new FlowDeleteTask(key); + FlowDeleteTask * task = new FlowDeleteTask(fe->key()); scheduler->Enqueue(task); WAIT_FOR(1000, 3000, FlowStatus(false)); }; FlowEntry *FlowFetch() { - FlowEntry *fe = FlowGet(vrf_, sip_, dip_, proto_, sport_, dport_, nh_id_); + uint16_t lookup_dport = dport_; + if (proto_ == IPPROTO_ICMPV6) { + lookup_dport = ICMP6_ECHO_REPLY; + } + FlowEntry *fe = FlowGet(vrf_, sip_, dip_, proto_, sport_, lookup_dport, + nh_id_); return fe; } diff --git a/src/vnsw/agent/pkt/test/test_pkt_util.cc b/src/vnsw/agent/pkt/test/test_pkt_util.cc index 592b0ba54cb..f170c33a7e6 100644 --- a/src/vnsw/agent/pkt/test/test_pkt_util.cc +++ b/src/vnsw/agent/pkt/test/test_pkt_util.cc @@ -219,7 +219,7 @@ void MakeIp6Packet(PktGen *pkt, int ifindex, const char *sip, const char *dip, pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:01", ETHERTYPE_IPV6); pkt->AddIp6Hdr(sip, dip, proto); if (proto == IPPROTO_ICMPV6) { - pkt->AddIcmpHdr(); + pkt->AddIcmp6Hdr(); } } @@ -304,7 +304,7 @@ void MakeIp6MplsPacket(PktGen *pkt, int ifindex, const char *out_sip, pkt->AddMplsHdr(label, true); pkt->AddIp6Hdr(sip, dip, proto); if (proto == IPPROTO_ICMPV6) { - pkt->AddIcmpHdr(); + pkt->AddIcmp6Hdr(); } } diff --git a/src/vnsw/agent/pkt/test/test_sg_flowv6.cc b/src/vnsw/agent/pkt/test/test_sg_flowv6.cc index ced233cffb8..15e99cc7520 100644 --- a/src/vnsw/agent/pkt/test/test_sg_flowv6.cc +++ b/src/vnsw/agent/pkt/test/test_sg_flowv6.cc @@ -412,7 +412,11 @@ class SgTestV6 : public ::testing::Test { bool ValidateAction(uint32_t vrfid, char *sip, char *dip, int proto, int sport, int dport, int action, uint32_t nh_id) { bool ret = true; - FlowEntry *fe = FlowGet(vrfid, sip, dip, proto, sport, dport, nh_id); + uint16_t lookup_dport = dport; + if (proto == IPPROTO_ICMPV6) { + lookup_dport = ICMP6_ECHO_REPLY; + } + FlowEntry *fe = FlowGet(vrfid, sip, dip, proto, sport, lookup_dport, nh_id); FlowEntry *rfe = fe->reverse_flow_entry(); EXPECT_TRUE((fe->match_p().sg_action & (1 << action)) != 0); diff --git a/src/vnsw/agent/test/pkt_gen.h b/src/vnsw/agent/test/pkt_gen.h index 6bb0495c117..62f97e66956 100644 --- a/src/vnsw/agent/test/pkt_gen.h +++ b/src/vnsw/agent/test/pkt_gen.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -352,6 +353,13 @@ class PktGen { len += sizeof(struct icmp) + len; }; + void AddIcmp6Hdr(uint8_t type=ICMP6_ECHO_REQUEST) { + struct icmp6_hdr *icmp = (struct icmp6_hdr *)(buff + len); + icmp->icmp6_type = type; + icmp->icmp6_code = 0; + len += sizeof(struct icmp6_hdr) + len; + }; + void AddGreHdr(uint16_t proto) { GreHdr *gre = (GreHdr *)(buff + len); gre->flags = 0; diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index 21a66e0e62c..001aa86cb2d 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -2837,6 +2837,9 @@ bool FlowDelete(const string &vrf_name, const char *sip, const char *dip, key.dst_addr = IpAddress::from_string(dip); key.src_port = sport; key.dst_port = dport; + if (proto == IPPROTO_ICMPV6) { + key.dst_port = ICMP6_ECHO_REPLY; + } key.protocol = proto; key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;