[ovs-dev] [PATCH v3 17/17] netdev: Add support for GENEVE/VXLAN tunnel segmentation
Pravin B Shelar
pshelar at ovn.org
Tue May 10 17:31:00 UTC 2016
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 <pshelar at ovn.org>
---
lib/dp-packet-lso.c | 32 +++++++++++++++++++++++++++++++-
lib/dp-packet-lso.h | 1 +
lib/netdev-native-tnl.c | 20 ++++++++++++++++----
lib/netdev-vport.c | 11 +++++------
4 files changed, 53 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 a716492..62ee945 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -227,20 +227,32 @@ netdev_tnl_push_udp_header(struct dp_packet *packet,
udp->udp_src = netdev_tnl_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) {
+ ovs_be32 udp_csum;
uint32_t csum;
+
if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) {
csum = packet_csum_pseudoheader6(netdev_tnl_ipv6_hdr(dp_packet_data(packet)));
} else {
csum = packet_csum_pseudoheader(netdev_tnl_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 c2f3f5f..225a8e6 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -212,10 +212,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);
@@ -223,11 +220,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
More information about the dev
mailing list