Skip to content

Commit

Permalink
Distribute mirroring packets to Ecmp destination
Browse files Browse the repository at this point in the history
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
  • Loading branch information
divakardhar committed Sep 30, 2016
1 parent 74698a2 commit 7de3127
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
37 changes: 28 additions & 9 deletions dp-core/vr_nexthop.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);

/*
Expand Down
2 changes: 2 additions & 0 deletions include/vr_packet.h
Expand Up @@ -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)
Expand Down

0 comments on commit 7de3127

Please sign in to comment.