From 7de3127323428ba8f1f62fbc72dfb79f3c2acf01 Mon Sep 17 00:00:00 2001 From: Divakar Date: Fri, 2 Sep 2016 23:25:39 +0530 Subject: [PATCH] Distribute mirroring packets to Ecmp destination Incase of dynamic mirroring, udp header is added on top of mirrored packet. If the mirroring destination is an Ecmp destination, ecmp distribution is happening using the newly added udp heder. This results in no distribution with in Ecmp, as all mirrored packets are going to contain the same IP/UDP header resulting in same hash calculation. As a fix, for a better distribution, the udp source port of the UDP header is calculated based on the packet's IP/IPV6 header content. This results in better port range, eventually leading to better Ecmp distribution. For non IP/IPV6 packets, Agent added port is taken as is. closes-bug: #1616822 Change-Id: I06f2fd0dee79ade11696bc2b2d9c3c34c374ff65 --- dp-core/vr_nexthop.c | 37 ++++++++++++++++++++++++++++--------- include/vr_packet.h | 2 ++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/dp-core/vr_nexthop.c b/dp-core/vr_nexthop.c index e6901e261..3ccc3aa94 100644 --- a/dp-core/vr_nexthop.c +++ b/dp-core/vr_nexthop.c @@ -430,7 +430,8 @@ nh_udp_tunnel_helper(struct vr_packet *pkt, unsigned short sport, } static bool -nh_udp_tunnel6_helper(struct vr_packet *pkt, struct vr_nexthop *nh) +nh_udp_tunnel6_helper(struct vr_packet *pkt, + struct vr_nexthop *nh, uint16_t sport, uint16_t dport) { unsigned int v4_ip; uint8_t *sip = NULL; @@ -466,8 +467,8 @@ nh_udp_tunnel6_helper(struct vr_packet *pkt, struct vr_nexthop *nh) return false; } - udp->udp_sport = nh->nh_udp_tun6_sport; - udp->udp_dport = nh->nh_udp_tun6_dport; + udp->udp_sport = sport; + udp->udp_dport = dport; udp->udp_length = htons(pkt_len(pkt)); udp->udp_csum = 0; @@ -1432,15 +1433,16 @@ static int nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, struct vr_forwarding_md *fmd) { - unsigned int head_space; - uint32_t sip = 0; - + int ret = -1; + unsigned int head_space, hash; + uint32_t sip = 0, port_range; struct vr_packet *tmp; struct vr_ip *ip; struct vr_ip6 *ip6; struct vr_udp *udp; struct vr_vrf_stats *stats; struct vr_forwarding_class_qos *qos; + struct vr_flow flow, *flowp = &flow; if (!fmd) goto send_fail; @@ -1462,6 +1464,23 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, pkt = tmp; } + fmd->fmd_udp_src_port = nh->nh_udp_tun_sport; + if (pkt->vp_type == VP_TYPE_IP) { + ret = vr_inet_get_flow_key(nh->nh_router, pkt, fmd, flowp); + } else if (pkt->vp_type == VP_TYPE_IP6) { + ip6 = (struct vr_ip6 *)pkt_network_header(pkt); + ret = vr_inet6_form_flow(nh->nh_router, fmd->fmd_dvrf, pkt, + fmd->fmd_vlan, ip6, flowp); + } + + if (!ret) { + hash = vr_hash(flowp, flowp->flow_key_len, 0); + port_range = VR_UDP_PORT_RANGE_END - VR_UDP_PORT_RANGE_START; + fmd->fmd_udp_src_port = (uint16_t) + (((uint64_t ) hash * port_range) >> 32); + fmd->fmd_udp_src_port += VR_UDP_PORT_RANGE_START; + } + if (nh->nh_family == AF_INET) { if (nh->nh_flags & NH_FLAG_TUNNEL_SIP_COPY) { sip = nh_generate_sip(nh, pkt); @@ -1472,7 +1491,7 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, } qos = vr_qos_get_forwarding_class(nh->nh_router, pkt, fmd); - if (nh_udp_tunnel_helper(pkt, nh->nh_udp_tun_sport, + if (nh_udp_tunnel_helper(pkt, fmd->fmd_udp_src_port, nh->nh_udp_tun_dport, sip, nh->nh_udp_tun_dip, qos) == false) { goto send_fail; @@ -1487,7 +1506,8 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, pkt->vp_flags |= VP_FLAG_CSUM_PARTIAL; } else if (nh->nh_family == AF_INET6) { - if (nh_udp_tunnel6_helper(pkt, nh) == false) { + if (nh_udp_tunnel6_helper(pkt, nh, fmd->fmd_udp_src_port, + nh->nh_udp_tun_dport) == false) { goto send_fail; } @@ -1497,7 +1517,6 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, pkt->vp_flags |= VP_FLAG_CSUM_PARTIAL; } - pkt_set_network_header(pkt, pkt->vp_data); /* diff --git a/include/vr_packet.h b/include/vr_packet.h index 4abc14325..f7097c4bb 100644 --- a/include/vr_packet.h +++ b/include/vr_packet.h @@ -302,6 +302,8 @@ struct vr_vlan_hdr { #define VR_ETH_PROTO_VLAN 0x8100 #define VR_DIAG_CSUM 0xffff +#define VR_UDP_PORT_RANGE_START 49152 +#define VR_UDP_PORT_RANGE_END 65535 static inline int8_t vr_vlan_get_tos(uint8_t *eth_data)