Commit 4be986c8 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'seg6-add-support-for-srv6-end-dt4-dt6-behavior'

Andrea Mayer says:

====================
seg6: add support for SRv6 End.DT4/DT6 behavior

This patchset provides support for the SRv6 End.DT4 and End.DT6 (VRF mode)
behaviors.

The SRv6 End.DT4 behavior is used to implement multi-tenant IPv4 L3 VPNs. It
decapsulates the received packets and performs IPv4 routing lookup in the
routing table of the tenant. The SRv6 End.DT4 Linux implementation leverages a
VRF device in order to force the routing lookup into the associated routing
table.
The SRv6 End.DT4 behavior is defined in the SRv6 Network Programming [1].

The Linux kernel already offers an implementation of the SRv6 End.DT6 behavior
which allows us to set up IPv6 L3 VPNs over SRv6 networks. This new
implementation of DT6 is based on the same VRF infrastructure already exploited
for implementing the SRv6 End.DT4 behavior. The aim of the new SRv6 End.DT6 in
VRF mode consists in simplifying the construction of IPv6 L3 VPN services in
the multi-tenant environment.
Currently, the two SRv6 End.DT6 implementations (legacy and VRF mode)
coexist seamlessly and can be chosen according to the context and the user
preferences.

- Patch 1 is needed to solve a pre-existing issue with tunneled packets
  when a sniffer is attached;

- Patch 2 improves the management of the seg6local attributes used by the
  SRv6 behaviors;

- Patch 3 adds support for optional attributes in SRv6 behaviors;

- Patch 4 introduces two callbacks used for customizing the
  creation/destruction of a SRv6 behavior;

- Patch 5 is the core patch that adds support for the SRv6 End.DT4
  behavior;

- Patch 6 introduces the VRF support for SRv6 End.DT6 behavior;

- Patch 7 adds the selftest for SRv6 End.DT4 behavior;

- Patch 8 adds the selftest for SRv6 End.DT6 (VRF mode) behavior.

Regarding iproute2, the support for the new "vrftable" attribute, required by
both SRv6 End.DT4 and End.DT6 (VRF mode) behaviors, is provided in a different
patchset that will follow shortly.

I would like to thank David Ahern for his support during the development of
this patchset.

[1] https://tools.ietf.org/html/draft-ietf-spring-srv6-network-programming
====================

Link: https://lore.kernel.org/r/20201202130517.4967-1-andrea.mayer@uniroma2.itSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 846c3c9c 2bc03553
...@@ -1310,6 +1310,61 @@ static void vrf_ip6_input_dst(struct sk_buff *skb, struct net_device *vrf_dev, ...@@ -1310,6 +1310,61 @@ static void vrf_ip6_input_dst(struct sk_buff *skb, struct net_device *vrf_dev,
skb_dst_set(skb, &rt6->dst); skb_dst_set(skb, &rt6->dst);
} }
static int vrf_prepare_mac_header(struct sk_buff *skb,
struct net_device *vrf_dev, u16 proto)
{
struct ethhdr *eth;
int err;
/* in general, we do not know if there is enough space in the head of
* the packet for hosting the mac header.
*/
err = skb_cow_head(skb, LL_RESERVED_SPACE(vrf_dev));
if (unlikely(err))
/* no space in the skb head */
return -ENOBUFS;
__skb_push(skb, ETH_HLEN);
eth = (struct ethhdr *)skb->data;
skb_reset_mac_header(skb);
/* we set the ethernet destination and the source addresses to the
* address of the VRF device.
*/
ether_addr_copy(eth->h_dest, vrf_dev->dev_addr);
ether_addr_copy(eth->h_source, vrf_dev->dev_addr);
eth->h_proto = htons(proto);
/* the destination address of the Ethernet frame corresponds to the
* address set on the VRF interface; therefore, the packet is intended
* to be processed locally.
*/
skb->protocol = eth->h_proto;
skb->pkt_type = PACKET_HOST;
skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
skb_pull_inline(skb, ETH_HLEN);
return 0;
}
/* prepare and add the mac header to the packet if it was not set previously.
* In this way, packet sniffers such as tcpdump can parse the packet correctly.
* If the mac header was already set, the original mac header is left
* untouched and the function returns immediately.
*/
static int vrf_add_mac_header_if_unset(struct sk_buff *skb,
struct net_device *vrf_dev,
u16 proto)
{
if (skb_mac_header_was_set(skb))
return 0;
return vrf_prepare_mac_header(skb, vrf_dev, proto);
}
static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -1336,10 +1391,16 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, ...@@ -1336,10 +1391,16 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
skb->skb_iif = vrf_dev->ifindex; skb->skb_iif = vrf_dev->ifindex;
if (!list_empty(&vrf_dev->ptype_all)) { if (!list_empty(&vrf_dev->ptype_all)) {
int err;
err = vrf_add_mac_header_if_unset(skb, vrf_dev,
ETH_P_IPV6);
if (likely(!err)) {
skb_push(skb, skb->mac_len); skb_push(skb, skb->mac_len);
dev_queue_xmit_nit(skb, vrf_dev); dev_queue_xmit_nit(skb, vrf_dev);
skb_pull(skb, skb->mac_len); skb_pull(skb, skb->mac_len);
} }
}
IP6CB(skb)->flags |= IP6SKB_L3SLAVE; IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
} }
...@@ -1381,10 +1442,15 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev, ...@@ -1381,10 +1442,15 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
vrf_rx_stats(vrf_dev, skb->len); vrf_rx_stats(vrf_dev, skb->len);
if (!list_empty(&vrf_dev->ptype_all)) { if (!list_empty(&vrf_dev->ptype_all)) {
int err;
err = vrf_add_mac_header_if_unset(skb, vrf_dev, ETH_P_IP);
if (likely(!err)) {
skb_push(skb, skb->mac_len); skb_push(skb, skb->mac_len);
dev_queue_xmit_nit(skb, vrf_dev); dev_queue_xmit_nit(skb, vrf_dev);
skb_pull(skb, skb->mac_len); skb_pull(skb, skb->mac_len);
} }
}
skb = vrf_rcv_nfhook(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, vrf_dev); skb = vrf_rcv_nfhook(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, vrf_dev);
out: out:
......
...@@ -26,6 +26,7 @@ enum { ...@@ -26,6 +26,7 @@ enum {
SEG6_LOCAL_IIF, SEG6_LOCAL_IIF,
SEG6_LOCAL_OIF, SEG6_LOCAL_OIF,
SEG6_LOCAL_BPF, SEG6_LOCAL_BPF,
SEG6_LOCAL_VRFTABLE,
__SEG6_LOCAL_MAX, __SEG6_LOCAL_MAX,
}; };
#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1) #define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment