diff options
author | Jesse Gross <jesse@nicira.com> | 2015-06-22 14:23:37 -0700 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2015-06-26 14:18:07 -0700 |
commit | 5bb08b0ef605a9b164399bd74a194ae1b921c3ea (patch) | |
tree | dc63682400cab6eb2fd50cc563d88aeb12a60ee6 /lib/netdev-vport.c | |
parent | daab0ae6bb558411f24cee6a7bb32599a5f9e363 (diff) | |
download | openvswitch-5bb08b0ef605a9b164399bd74a194ae1b921c3ea.tar.gz |
tunneling: Userspace datapath support for Geneve options.
Currently the userspace datapath only supports Geneve in a
basic mode - without options - since the rest of userspace
previously didn't support options either. This enables the
userspace datapath to send and receive options as well.
The receive path for extracting the tunnel options isn't entirely
optimal because it does a lookup on the options on a per-packet
basis, rather than per-flow like the kernel does. This is not
as straightforward to do in the userspace datapath since there
is no translation step between packet formats used in packet vs.
flow lookup. This can be optimized in the future and in the
meantime option support is still useful for testing and simulation.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/netdev-vport.c')
-rw-r--r-- | lib/netdev-vport.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index ea9abf9e7..259d0ed4d 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -1199,6 +1199,7 @@ netdev_geneve_pop_header(struct dp_packet *packet) struct flow_tnl *tnl = &md->tunnel; struct genevehdr *gnh; unsigned int hlen; + int err; memset(md, 0, sizeof *md); if (GENEVE_BASE_HLEN > dp_packet_size(packet)) { @@ -1224,12 +1225,6 @@ netdev_geneve_pop_header(struct dp_packet *packet) return EINVAL; } - if (gnh->opt_len && gnh->critical) { - VLOG_WARN_RL(&err_rl, "unknown geneve critical options: %"PRIu8" bytes\n", - gnh->opt_len * 4); - return EINVAL; - } - if (gnh->proto_type != htons(ETH_TYPE_TEB)) { VLOG_WARN_RL(&err_rl, "unknown geneve encapsulated protocol: %#x\n", ntohs(gnh->proto_type)); @@ -1240,6 +1235,13 @@ netdev_geneve_pop_header(struct dp_packet *packet) tnl->tun_id = htonll(ntohl(get_16aligned_be32(&gnh->vni)) >> 8); tnl->flags |= FLOW_TNL_F_KEY; + err = tun_metadata_from_geneve_header(gnh->options, gnh->opt_len * 4, + &tnl->metadata); + if (err) { + VLOG_WARN_RL(&err_rl, "invalid geneve options"); + return err; + } + dp_packet_reset_packet(packet, hlen); return 0; @@ -1253,6 +1255,8 @@ netdev_geneve_build_header(const struct netdev *netdev, struct netdev_vport *dev = netdev_vport_cast(netdev); struct netdev_tunnel_config *tnl_cfg; struct genevehdr *gnh; + int opt_len; + bool crit_opt; /* XXX: RCUfy tnl_cfg. */ ovs_mutex_lock(&dev->mutex); @@ -1260,12 +1264,19 @@ netdev_geneve_build_header(const struct netdev *netdev, gnh = udp_build_header(tnl_cfg, tnl_flow, data); - gnh->oam = !!(tnl_flow->tunnel.flags & FLOW_TNL_F_OAM); - gnh->proto_type = htons(ETH_TYPE_TEB); put_16aligned_be32(&gnh->vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8)); ovs_mutex_unlock(&dev->mutex); - data->header_len = GENEVE_BASE_HLEN; + + opt_len = tun_metadata_to_geneve_header(&tnl_flow->tunnel.metadata, + gnh->options, &crit_opt); + + gnh->opt_len = opt_len / 4; + gnh->oam = !!(tnl_flow->tunnel.flags & FLOW_TNL_F_OAM); + gnh->critical = crit_opt ? 1 : 0; + gnh->proto_type = htons(ETH_TYPE_TEB); + + data->header_len = GENEVE_BASE_HLEN + opt_len; data->tnl_type = OVS_VPORT_TYPE_GENEVE; return 0; } |