summaryrefslogtreecommitdiff
path: root/ofproto
diff options
context:
space:
mode:
authorJan Scheurich <jan.scheurich@ericsson.com>2017-06-02 16:16:21 +0000
committerBen Pfaff <blp@ovn.org>2017-06-02 14:40:34 -0700
commit63171f047fe20ef62ce0c42c4b9da2114ddd4bff (patch)
treec6666b342ea6346e43436e0a182e909ebbba733b /ofproto
parentbeb75a40fdc295bfd6521b0068b4cd12f6de507c (diff)
downloadopenvswitch-63171f047fe20ef62ce0c42c4b9da2114ddd4bff.tar.gz
userspace: L3 tunnel support for GRE and LISP
Add a boolean "layer3" configuration option for tunnel vports. The layer3 option defaults to false for all ports except LISP. GRE ports accept both true and false for "layer3". A tunnel vport configured with layer3=true receives L3 packets. which are then converted to Ethernet packets by pushing a dummy Ethernet heder at the ingress of the OpenFlow pipeline. The Ethernet header of a packet is stripped before sending to a layer3 tunnel vport. Presently a single GRE vport cannot carry both L2 and L3 packets. But it is possible to create two GRE vports representing the same GRE tunel, one with layer3=false, the other with layer3=true. L2 packet from the tunnel are received on the first vport, L3 packets on the second. The controller must send packets to the layer3 GRE vport to tunnel them without their Ethernet header. Units tests have been added to check the L3 tunnel handling. LISP tunnels are not yet supported by the netdev userspace datapath. Signed-off-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: Jiri Benc <jbenc@redhat.com> Signed-off-by: Yi Yang <yi.y.yang@intel.com> Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com> Co-authored-by: Zoltan Balogh <zoltan.balogh@ericsson.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ofproto')
-rw-r--r--ofproto/tunnel.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index 2a086623d..e27a9fb75 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -38,6 +38,7 @@
#include "openvswitch/vlog.h"
#include "unaligned.h"
#include "ofproto-dpif.h"
+#include "netdev-vport.h"
VLOG_DEFINE_THIS_MODULE(tunnel);
@@ -49,6 +50,7 @@ struct tnl_match {
bool in_key_flow;
bool ip_src_flow;
bool ip_dst_flow;
+ bool is_layer3;
};
struct tnl_port {
@@ -162,6 +164,7 @@ tnl_port_add__(const struct ofport_dpif *ofport, const struct netdev *netdev,
tnl_port->match.ip_dst_flow = cfg->ip_dst_flow;
tnl_port->match.in_key_flow = cfg->in_key_flow;
tnl_port->match.odp_port = odp_port;
+ tnl_port->match.is_layer3 = netdev_vport_is_layer3(netdev);
map = tnl_match_map(&tnl_port->match);
existing_port = tnl_find_exact(&tnl_port->match, *map);
@@ -205,7 +208,8 @@ tnl_port_add__(const struct ofport_dpif *ofport, const struct netdev *netdev,
* Returns 0 if successful, otherwise a positive errno value. */
int
tnl_port_add(const struct ofport_dpif *ofport, const struct netdev *netdev,
- odp_port_t odp_port, bool native_tnl, const char name[]) OVS_EXCLUDED(rwlock)
+ odp_port_t odp_port, bool native_tnl, const char name[])
+ OVS_EXCLUDED(rwlock)
{
bool ok;
@@ -232,7 +236,8 @@ tnl_port_reconfigure(const struct ofport_dpif *ofport,
fat_rwlock_wrlock(&rwlock);
tnl_port = tnl_find_ofport(ofport);
if (!tnl_port) {
- changed = tnl_port_add__(ofport, netdev, odp_port, false, native_tnl, name);
+ changed = tnl_port_add__(ofport, netdev, odp_port, false, native_tnl,
+ name);
} else if (tnl_port->netdev != netdev
|| tnl_port->match.odp_port != odp_port
|| tnl_port->change_seq != netdev_get_change_seq(tnl_port->netdev)) {
@@ -383,7 +388,6 @@ tnl_wc_init(struct flow *flow, struct flow_wildcards *wc)
}
/* Match on packet_type for tunneled packets.*/
wc->masks.packet_type = OVS_BE32_MAX;
-
}
}
@@ -562,6 +566,7 @@ tnl_find(const struct flow *flow) OVS_REQ_RDLOCK(rwlock)
match.in_key_flow = in_key_flow;
match.ip_dst_flow = ip_dst_flow;
match.ip_src_flow = ip_src == IP_SRC_FLOW;
+ match.is_layer3 = flow->packet_type != htonl(PT_ETH);
tnl_port = tnl_find_exact(&match, map);
if (tnl_port) {
@@ -611,6 +616,9 @@ tnl_match_fmt(const struct tnl_match *match, struct ds *ds)
} else {
ds_put_format(ds, ", key=%#"PRIx64, ntohll(match->in_key));
}
+ if (match->is_layer3) {
+ ds_put_cstr(ds, ", layer3");
+ }
ds_put_format(ds, ", dp port=%"PRIu32, match->odp_port);
}