Skip to content

Commit

Permalink
Add support for LISP tunneling
Browse files Browse the repository at this point in the history
LISP is an experimental layer 3 tunneling protocol, described in RFC
6830.  This patch adds support for LISP tunneling.  Since LISP
encapsulated packets do not carry an Ethernet header, it is removed
before encapsulation, and added with hardcoded source and destination
MAC addresses after decapsulation.  The harcoded MAC chosen for this
purpose is the locally administered address 02:00:00:00:00:00.  Flow
actions can be used to rewrite this MAC for correct reception.  As such,
this patch is intended to be used for static network configurations, or
with a LISP capable controller.

Signed-off-by: Lorand Jakab <[email protected]>
Signed-off-by: Kyle Mestery <[email protected]>
Signed-off-by: Jesse Gross <[email protected]>
  • Loading branch information
ljakab authored and jessegross committed Feb 25, 2013
1 parent 54e536a commit a6ae068
Show file tree
Hide file tree
Showing 19 changed files with 627 additions and 39 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Keith Amidon [email protected]
Krishna Kondaka [email protected]
Kyle Mestery [email protected]
Leo Alterman [email protected]
Lorand Jakab [email protected]
Luca Giraudo [email protected]
Martin Casado [email protected]
Mehak Mahajan [email protected]
Expand Down
2 changes: 1 addition & 1 deletion FAQ
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ Q: What features are not available in the Open vSwitch kernel datapath

A: The kernel module in upstream Linux 3.3 and later does not include
tunnel virtual ports, that is, interfaces with type "gre",
"ipsec_gre", "gre64", "ipsec_gre64", or "vxlan". It is
"ipsec_gre", "gre64", "ipsec_gre64", "vxlan", or "lisp". It is
possible to create tunnels in Linux and attach them to Open vSwitch
as system devices. However, they cannot be dynamically created
through the OVSDB protocol or set the tunnel ids as a flow action.
Expand Down
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ EXTRA_DIST = \
OPENFLOW-1.1+ \
PORTING \
README-gcov \
README-lisp \
REPORTING-BUGS \
SubmittingPatches \
WHY-OVS \
Expand Down
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ post-v1.10.0
- Stable bond mode has been removed.
- The autopath action has been removed.
- CAPWAP tunneling support removed.
- New support for the data encapsulation format of the LISP tunnel
protocol (RFC 6830). An external control plane or manual flow
setup is required for EID-to-RLOC mapping.


v1.10.0 - xx xxx xxxx
Expand Down
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ vSwitch supports the following features:
* NIC bonding with or without LACP on upstream switch
* NetFlow, sFlow(R), and mirroring for increased visibility
* QoS (Quality of Service) configuration, plus policing
* GRE, GRE over IPSEC, and VXLAN tunneling
* GRE, GRE over IPSEC, VXLAN, and LISP tunneling
* 802.1ag connectivity fault management
* OpenFlow 1.0 plus numerous extensions
* Transactional configuration database with C and Python bindings
Expand Down
68 changes: 68 additions & 0 deletions README-lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Using LISP tunneling
====================

LISP is a layer 3 tunneling mechanism, meaning that encapsulated packets do
not carry Ethernet headers, and ARP requests shouldn't be sent over the
tunnel. Because of this, there are some additional steps required for setting
up LISP tunnels in Open vSwitch, until support for L3 tunnels will improve.

This guide assumes a point-to-point tunnel between two VMs connected to OVS
bridges on different hypervisors connected via IPv4. Of course, more than one
VM may be connected to any of the hypervisors, using the same LISP tunnel, and
a hypervisor may be connected to several hypervisors over different LISP
tunnels.

There are several scenarios:

1) the VMs have IP addresses in the same subnet and the hypervisors are also
in a single subnet (although one different from the VM's);
2) the VMs have IP addresses in the same subnet but the hypervisors are
separated by a router;
3) the VMs are in different subnets.

In cases 1) and 3) ARP resolution can work as normal: ARP traffic is
configured not to go through the LISP tunnel. For case 1) ARP is able to
reach the other VM, if both OVS instances default to MAC address learning.
Case 3) requires the hypervisor be configured as the default router for the
VMs.

In case 2) the VMs expect ARP replies from each other, but this is not
possible over a layer 3 tunnel. One solution is to have static MAC address
entries preconfigured on the VMs (e.g., `arp -f /etc/ethers` on startup on
Unix based VMs), or have the hypervisor do proxy ARP.

On the receiving side, the packet arrives without the original MAC header.
The LISP tunneling code attaches a header with harcoded source and destination
MAC addres 02:00:00:00:00:00. This address has all bits set to 0, except the
locally administered bit, in order to avoid potential collisions with existing
allocations. In order for packets to reach their intended destination, the
destination MAC address needs to be rewritten. This can be done using the
flow table.

See below for an example setup, and the associated flow rules to enable LISP
tunneling.

+---+ +---+
|VM1| |VM2|
+---+ +---+
| |
+--[tap0]--+ +--[tap0]---+
| | | |
[lisp0] OVS1 [eth0]-----------------[eth0] OVS2 [lisp0]
| | | |
+----------+ +-----------+

On each hypervisor, interfaces tap0, eth0, and lisp0 are added to a single
bridge instance, and become numbered 1, 2, and 3 respectively:

ovs-vsctl add-br br0
ovs-vsctl add-port br0 tap0
ovs-vsctl add-port br0 eth0
ovs-vsctl add-port br0 lisp0 -- set Interface lisp0 type=lisp options:remote_ip=<OVSx_IP>

Flows on br0 are configured as follows:

priority=3,dl_dst=02:00:00:00:00:00,action=mod_dl_dst:<VMx_MAC>,output:1
priority=2,in_port=1,dl_type=0x0806,action=NORMAL
priority=1,in_port=1,dl_type=0x0800,vlan_tci=0,nw_src=<EID_prefix>,action=output:3
priority=0,action=NORMAL
1 change: 1 addition & 0 deletions datapath/Modules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ openvswitch_sources = \
vport.c \
vport-gre.c \
vport-internal_dev.c \
vport-lisp.c \
vport-netdev.c \
vport-vxlan.c

Expand Down
1 change: 1 addition & 0 deletions datapath/linux/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
/vport-generic.c
/vport-gre.c
/vport-internal_dev.c
/vport-lisp.c
/vport-netdev.c
/vport-patch.c
/vport-vxlan.c
Expand Down
15 changes: 15 additions & 0 deletions datapath/tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,21 @@ static int send_frags(struct sk_buff *skb,
return sent_len;
}

/* Compute source UDP port for outgoing packet.
* Currently we use the flow hash.
*/
u16 ovs_tnl_get_src_port(struct sk_buff *skb)
{
int low;
int high;
unsigned int range;
u32 hash = OVS_CB(skb)->flow->hash;

inet_get_local_port_range(&low, &high);
range = (high - low) + 1;
return (((u64) hash * range) >> 32) + low;
}

int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
{
struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
Expand Down
2 changes: 2 additions & 0 deletions datapath/tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#define TNL_T_PROTO_GRE 0
#define TNL_T_PROTO_GRE64 1
#define TNL_T_PROTO_VXLAN 3
#define TNL_T_PROTO_LISP 4

/* These flags are only needed when calling tnl_find_port(). */
#define TNL_T_KEY_EXACT (1 << 10)
Expand Down Expand Up @@ -158,6 +159,7 @@ int ovs_tnl_get_options(const struct vport *, struct sk_buff *);
const char *ovs_tnl_get_name(const struct vport *vport);
int ovs_tnl_send(struct vport *vport, struct sk_buff *skb);
void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb);
u16 ovs_tnl_get_src_port(struct sk_buff *skb);

struct vport *ovs_tnl_find_port(struct net *net, __be32 saddr, __be32 daddr,
__be64 key, int tunnel_type,
Expand Down
Loading

0 comments on commit a6ae068

Please sign in to comment.