diff --git a/dp-core/vr_nexthop.c b/dp-core/vr_nexthop.c index fff09db51..5849ec906 100644 --- a/dp-core/vr_nexthop.c +++ b/dp-core/vr_nexthop.c @@ -1229,10 +1229,25 @@ nh_discard(struct vr_packet *pkt, struct vr_nexthop *nh, return 0; } +static int +nh_generate_sip(struct vr_nexthop *nh, struct vr_packet *pkt) +{ + struct vr_ip *iph; + + iph = (struct vr_ip *)pkt_network_header(pkt); + if (pkt->vp_type == VP_TYPE_IP) { + return iph->ip_saddr; + } + + return 0; +} + static int nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, struct vr_forwarding_md *fmd) { + uint32_t sip = 0; + struct vr_packet *tmp; struct vr_ip *ip; struct vr_udp *udp; @@ -1251,11 +1266,32 @@ nh_udp_tunnel(struct vr_packet *pkt, struct vr_nexthop *nh, goto send_fail; } - if (nh_udp_tunnel_helper(pkt, nh->nh_udp_tun_sport, - nh->nh_udp_tun_dport, nh->nh_udp_tun_sip, - nh->nh_udp_tun_dip) == false) { + if (nh->nh_family == AF_INET) { + if (nh->nh_flags & NH_FLAG_TUNNEL_SIP_COPY) { + sip = nh_generate_sip(nh, pkt); + } + + if (!sip) { + sip = nh->nh_udp_tun_sip; + } + + if (nh_udp_tunnel_helper(pkt, nh->nh_udp_tun_sport, + nh->nh_udp_tun_dport, sip, + nh->nh_udp_tun_dip) == false) { + goto send_fail; + } + + if (pkt_len(pkt) > ((1 << sizeof(ip->ip_len) * 8))) + goto send_fail; + + ip = (struct vr_ip *)(pkt_data(pkt)); + udp = (struct vr_udp *)((char *)ip + ip->ip_hl * 4); + udp->udp_csum = vr_ip_partial_csum(ip); + + } else { goto send_fail; } + pkt_set_network_header(pkt, pkt->vp_data); if (pkt_len(pkt) > ((1 << sizeof(ip->ip_len) * 8))) diff --git a/include/vr_nexthop.h b/include/vr_nexthop.h index d2bec33a5..847b2fac4 100644 --- a/include/vr_nexthop.h +++ b/include/vr_nexthop.h @@ -55,6 +55,7 @@ enum nexthop_type { #define NH_FLAG_VNID 0x08000 #define NH_FLAG_ROUTE_LOOKUP 0x10000 #define NH_FLAG_UNKNOWN_UC_FLOOD 0x20000 +#define NH_FLAG_TUNNEL_SIP_COPY 0x40000 #define NH_SOURCE_INVALID 0 #define NH_SOURCE_VALID 1 diff --git a/utils/nh.c b/utils/nh.c index 1889366f7..488a9a140 100644 --- a/utils/nh.c +++ b/utils/nh.c @@ -166,6 +166,10 @@ nh_flags(uint32_t flags, uint8_t type, char *ptr) case NH_FLAG_UNKNOWN_UC_FLOOD: strcat(ptr, "Unicast Flood, "); break; + + case NH_FLAG_TUNNEL_SIP_COPY: + strcat(ptr, "Copy SIP, "); + break; } } return ptr;