This patch adds support to segment large UDP based tunnel packet. With this patch large packet generated by STT can be forwarded over to GENEVE/VXLAN port.
Signed-off-by: Pravin B Shelar <pshe...@ovn.org> --- lib/dp-packet-lso.c | 32 +++++++++++++++++++++++++++++++- lib/dp-packet-lso.h | 1 + lib/netdev-native-tnl.c | 19 +++++++++++++++---- lib/netdev-vport.c | 11 +++++------ 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/lib/dp-packet-lso.c b/lib/dp-packet-lso.c index bdcc987..c40ffd2 100644 --- a/lib/dp-packet-lso.c +++ b/lib/dp-packet-lso.c @@ -235,11 +235,41 @@ segment_gre_packet(struct dp_packet *orig) } static struct dp_packet * +segment_udp_tnl_packet(struct dp_packet *orig) +{ + struct dp_packet *seg_list, *seg; + uint8_t l2_pad_size = orig->l2_pad_size; + uint16_t l2_5_ofs = orig->l2_5_ofs; + uint16_t l3_ofs = orig->l3_ofs; + uint16_t l4_ofs = orig->l4_ofs; + + seg_list = segment_eth_packet(orig, orig->lso.outer_hlen); + restore_outer_headers(orig, orig->lso.outer_hlen, l2_pad_size, l2_5_ofs, + l3_ofs, l4_ofs); + + FOR_EACH_LSO_SEG(seg_list, seg) { + struct udp_header *udp; + restore_outer_headers(seg, orig->lso.outer_hlen, l2_pad_size, l2_5_ofs, + l3_ofs, l4_ofs); + + udp = dp_packet_l4(seg); + udp->udp_len = htons(dp_packet_size(seg) - seg->l4_ofs); + if (udp->udp_csum) { + fixup_segment_cheksum(seg, orig, UDP_CSUM_OFFSET); + } + } + return seg_list; +} + +static struct dp_packet * segment_l4_packet(struct dp_packet *orig) { if (orig->lso.type & DPBUF_LSO_GRE) { orig->lso.type &= ~DPBUF_LSO_GRE; return segment_gre_packet(orig); + } else if (orig->lso.type & DPBUF_LSO_UDP_TNL) { + orig->lso.type &= ~DPBUF_LSO_UDP_TNL; + return segment_udp_tnl_packet(orig); } else if (orig->lso.type & (DPBUF_LSO_TCPv4 | DPBUF_LSO_TCPv6)) { return segment_tcp_packet(orig); } else if (orig->lso.type & (DPBUF_LSO_UDPv4 | DPBUF_LSO_UDPv6)) { @@ -258,7 +288,7 @@ segment_ipv4_packet(struct dp_packet *orig) int ip_offset = 0; bool inc_ip_id = false; - if (orig->lso.type & (DPBUF_LSO_TCPv4 | DPBUF_LSO_GRE)) { + if (orig->lso.type & (DPBUF_LSO_TCPv4 | DPBUF_LSO_GRE | DPBUF_LSO_UDP_TNL)) { inc_ip_id = true; ip_id = ntohs(orig_iph->ip_id); } diff --git a/lib/dp-packet-lso.h b/lib/dp-packet-lso.h index fdf93a6..8d1cf03 100644 --- a/lib/dp-packet-lso.h +++ b/lib/dp-packet-lso.h @@ -32,6 +32,7 @@ #define DPBUF_LSO_UDPv4 (1 << 2) #define DPBUF_LSO_UDPv6 (1 << 3) #define DPBUF_LSO_GRE (1 << 4) +#define DPBUF_LSO_UDP_TNL (1 << 5) struct dp_packet_lso_ctx { struct dp_packet *next; /* Used to list lso segments. */ diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index 60cb81f..34d0f7a 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -227,20 +227,31 @@ push_udp_header(struct dp_packet *packet, udp->udp_src = get_src_port(packet); udp->udp_len = htons(ip_tot_size); + if (packet->lso.type) { + packet->lso.type |= DPBUF_LSO_UDP_TNL; + packet->lso.outer_hlen = data->header_len; + } if (udp->udp_csum) { uint32_t csum; + ovs_be32 udp_csum; + if (is_header_ipv6(dp_packet_data(packet))) { csum = packet_csum_pseudoheader6(ipv6_hdr(dp_packet_data(packet))); } else { csum = packet_csum_pseudoheader(ip_hdr(dp_packet_data(packet))); } - csum = csum_continue(csum, udp, ip_tot_size); - udp->udp_csum = csum_finish(csum); + if (packet->lso.type) { + udp_csum = ~csum_finish(csum); + } else { + csum = csum_continue(csum, udp, ip_tot_size); + udp_csum = csum_finish(csum); - if (!udp->udp_csum) { - udp->udp_csum = htons(0xffff); + if (!udp_csum) { + udp_csum = htons(0xffff); + } } + udp->udp_csum = udp_csum; } } diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 5530818..e158a51 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -207,10 +207,7 @@ netdev_vport_construct(struct netdev *netdev_) eth_addr_random(&dev->etheraddr); /* Add a default destination port for tunnel ports if none specified. */ - if (!strcmp(type, "gre")) { - netdev_->supported_lso_types = DPBUF_LSO_TCPv4 | DPBUF_LSO_TCPv6 | - DPBUF_LSO_UDPv4 | DPBUF_LSO_UDPv6; - } else if (!strcmp(type, "geneve")) { + if (!strcmp(type, "geneve")) { dev->tnl_cfg.dst_port = htons(GENEVE_DST_PORT); } else if (!strcmp(type, "vxlan")) { dev->tnl_cfg.dst_port = htons(VXLAN_DST_PORT); @@ -218,11 +215,13 @@ netdev_vport_construct(struct netdev *netdev_) dev->tnl_cfg.dst_port = htons(LISP_DST_PORT); } else if (!strcmp(type, "stt")) { dev->tnl_cfg.dst_port = htons(STT_DST_PORT); + netdev_stt_class_init(); + } + if (strcmp(type, "lisp")) { + /* All tunnels except lisp is implemented in userspace. */ netdev_->supported_lso_types = DPBUF_LSO_TCPv4 | DPBUF_LSO_TCPv6 | DPBUF_LSO_UDPv4 | DPBUF_LSO_UDPv6; - netdev_stt_class_init(); } - dev->tnl_cfg.dont_fragment = true; dev->tnl_cfg.ttl = DEFAULT_TTL; return 0; -- 2.5.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev