Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c8702c6 authored by David Lebrun's avatar David Lebrun Committed by David S. Miller
Browse files

ipv6: sr: add support for SRH encapsulation and injection with lwtunnels



This patch creates a new type of interfaceless lightweight tunnel (SEG6),
enabling the encapsulation and injection of SRH within locally emitted
packets and forwarded packets.

>From a configuration viewpoint, a seg6 tunnel would be configured as follows:

  ip -6 ro ad fc00::1/128 encap seg6 mode encap segs fc42::1,fc42::2,fc42::3 dev eth0

Any packet whose destination address is fc00::1 would thus be encapsulated
within an outer IPv6 header containing the SRH with three segments, and would
actually be routed to the first segment of the list. If `mode inline' was
specified instead of `mode encap', then the SRH would be directly inserted
after the IPv6 header without outer encapsulation.

The inline mode is only available if CONFIG_IPV6_SEG6_INLINE is enabled. This
feature was made configurable because direct header insertion may break
several mechanisms such as PMTUD or IPSec AH.

Signed-off-by: default avatarDavid Lebrun <david.lebrun@uclouvain.be>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 915d7e5e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
#ifndef _LINUX_SEG6_IPTUNNEL_H
#define _LINUX_SEG6_IPTUNNEL_H

#include <uapi/linux/seg6_iptunnel.h>

#endif
+6 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#include <linux/net.h>
#include <linux/ipv6.h>
#include <net/lwtunnel.h>
#include <linux/seg6.h>

static inline void update_csum_diff4(struct sk_buff *skb, __be32 from,
				     __be32 to)
@@ -48,5 +50,9 @@ static inline struct seg6_pernet_data *seg6_pernet(struct net *net)

extern int seg6_init(void);
extern void seg6_exit(void);
extern int seg6_iptunnel_init(void);
extern void seg6_iptunnel_exit(void);

extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len);

#endif
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ enum lwtunnel_encap_types {
	LWTUNNEL_ENCAP_IP,
	LWTUNNEL_ENCAP_ILA,
	LWTUNNEL_ENCAP_IP6,
	LWTUNNEL_ENCAP_SEG6,
	__LWTUNNEL_ENCAP_MAX,
};

+44 −0
Original line number Diff line number Diff line
/*
 *  SR-IPv6 implementation
 *
 *  Author:
 *  David Lebrun <david.lebrun@uclouvain.be>
 *
 *
 *  This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */

#ifndef _UAPI_LINUX_SEG6_IPTUNNEL_H
#define _UAPI_LINUX_SEG6_IPTUNNEL_H

enum {
	SEG6_IPTUNNEL_UNSPEC,
	SEG6_IPTUNNEL_SRH,
	__SEG6_IPTUNNEL_MAX,
};
#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)

struct seg6_iptunnel_encap {
	int mode;
	struct ipv6_sr_hdr srh[0];
};

#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3))

enum {
	SEG6_IPTUN_MODE_INLINE,
	SEG6_IPTUN_MODE_ENCAP,
};

static inline size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo)
{
	int encap = (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP);

	return ((tuninfo->srh->hdrlen + 1) << 3) +
	       (encap * sizeof(struct ipv6hdr));
}

#endif
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
		return "MPLS";
	case LWTUNNEL_ENCAP_ILA:
		return "ILA";
	case LWTUNNEL_ENCAP_SEG6:
		return "SEG6";
	case LWTUNNEL_ENCAP_IP6:
	case LWTUNNEL_ENCAP_IP:
	case LWTUNNEL_ENCAP_NONE:
Loading