2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 22:35:15 +00:00

compat: Add ipv6 GRE and IPV6 Tunneling

This patch backports upstream ipv6 GRE and tunneling into the OVS
OOT (Out of Tree) datapath drivers.  The primary reason for this
is to support the ERSPAN feature.

Because there is no previous history of ipv6 GRE and tunneling it is
not possible to exactly reproduce the history of all the files in
the patch.  The two newly added files - ip6_gre.c and ip6_tunnel.c -
are cut from whole cloth out of the upstream Linux 4.15 kernel and
then modified as necessary with compatibility layer fixups.
These two files already included parts of several other upstream
commits that also touched other upstream files.  As such, this
patch may incorporate parts or all of the following commits:

d350a82 net: erspan: create erspan metadata uapi header
c69de58 net: erspan: use bitfield instead of mask and offset
b423d13 net: erspan: fix use-after-free
214bb1c net: erspan: remove md NULL check
afb4c97 ip6_gre: fix potential memory leak in ip6erspan_rcv
50670b6 ip_gre: fix potential memory leak in erspan_rcv
a734321 ip6_gre: fix error path when ip6erspan_rcv failed
dd8d5b8 ip_gre: fix error path when erspan_rcv failed
293a199 ip6_gre: fix a pontential issue in ip6erspan_rcv
d91e8db5 net: erspan: reload pointer after pskb_may_pull
ae3e133 net: erspan: fix wrong return value
c05fad5 ip_gre: fix wrong return value of erspan_rcv
94d7d8f ip6_gre: add erspan v2 support
f551c91 net: erspan: introduce erspan v2 for ip_gre
1d7e2ed net: erspan: refactor existing erspan code
ef7baf5 ip6_gre: add ip6 erspan collect_md mode
5a963eb ip6_gre: Add ERSPAN native tunnel support
ceaa001 openvswitch: Add erspan tunnel support.
f192970 ip_gre: check packet length and mtu correctly in erspan tx
c84bed4 ip_gre: erspan device should keep dst
c122fda ip_gre: set tunnel hlen properly in erspan_tunnel_init
5513d08 ip_gre: check packet length and mtu correctly in erspan_xmit
935a974 ip_gre: get key from session_id correctly in erspan_rcv
1a66a83 gre: add collect_md mode to ERSPAN tunnel
84e54fe gre: introduce native tunnel support for ERSPAN

In cases where the listed commits also touched other source code
files then the patches are also listed separately within this
patch series.

Signed-off-by: Greg Rose <gvrose8192@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: William Tu <u9012063@gmail.com>
This commit is contained in:
Greg Rose
2018-03-05 10:11:57 -08:00
committed by Ben Pfaff
parent e987c48a6f
commit c387d8177f
17 changed files with 5320 additions and 33 deletions

View File

@@ -13,6 +13,8 @@ openvswitch_sources += \
linux/compat/ip_tunnel.c \
linux/compat/ip_tunnels_core.c \
linux/compat/ip6_output.c \
linux/compat/ip6_gre.c \
linux/compat/ip6_tunnel.c \
linux/compat/lisp.c \
linux/compat/netdevice.c \
linux/compat/nf_conntrack_core.c \

View File

@@ -11,4 +11,8 @@
#define __rcu
#endif
#ifndef READ_ONCE
#define READ_ONCE(x) (x)
#endif
#endif

View File

@@ -27,6 +27,10 @@
#define ETH_P_ERSPAN 0x88BE /* ERSPAN TYPE II */
#endif
#ifndef ETH_P_ERSPAN2
#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */
#endif
#define inner_eth_hdr rpl_inner_eth_hdr
static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb)
{

View File

@@ -316,4 +316,11 @@ static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
skb->mac_len = mac_len;
}
#endif
#ifndef HAVE_NETIF_KEEP_DST
static inline void netif_keep_dst(struct net_device *dev)
{
}
#endif
#endif /* __LINUX_NETDEVICE_WRAPPER_H */

View File

@@ -238,6 +238,9 @@ enum ovs_vport_type {
OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */
OVS_VPORT_TYPE_LISP = 105, /* LISP tunnel */
OVS_VPORT_TYPE_STT = 106, /* STT tunnel */
OVS_VPORT_TYPE_ERSPAN = 107, /* ERSPAN tunnel. */
OVS_VPORT_TYPE_IP6ERSPAN = 108, /* ERSPAN tunnel. */
OVS_VPORT_TYPE_IP6GRE = 109,
__OVS_VPORT_TYPE_MAX
};

View File

@@ -421,4 +421,15 @@ static inline void *skb_put_zero(struct sk_buff *skb, unsigned int len)
}
#endif
#ifndef HAVE_SKB_GSO_IPXIP6
#define SKB_GSO_IPXIP6 (1 << 10)
#endif
#ifndef HAVE_SKB_SET_INNER_IPPROTO
static inline void skb_set_inner_ipproto(struct sk_buff *skb,
__u8 ipproto)
{
}
#endif
#endif

View File

@@ -1,4 +1,4 @@
#ifndef USE_UPSTREAM_TUNNEL
#ifndef HAVE_LINUX_ERSPAN_H
#ifndef __LINUX_ERSPAN_H
#define __LINUX_ERSPAN_H
@@ -16,7 +16,7 @@
* s, Recur, Flags, Version fields only S (bit 03) is set to 1. The
* other fields are set to zero, so only a sequence number follows.
*
* ERSPAN Type II header (8 octets [42:49])
* ERSPAN Version 1 (Type II) header (8 octets [42:49])
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -25,11 +25,66 @@
* | Reserved | Index |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
* ERSPAN Version 2 (Type III) header (12 octets [42:49])
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Ver | VLAN | COS |BSO|T| Session ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Timestamp |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SGT |P| FT | Hw ID |D|Gra|O|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Platform Specific SubHeader (8 octets, optional)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Platf ID | Platform Specific Info |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Platform Specific Info |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB
*/
#define ERSPAN_VERSION 0x1
/* #include <uapi/linux/erspan.h> */
/* Just insert uapi/linux/erspan.h here since
* we don't pull in uapi to compat
*/
/* ERSPAN version 2 metadata header */
struct erspan_md2 {
__be32 timestamp;
__be16 sgt; /* security group tag */
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 hwid_upper:2,
ft:5,
p:1;
__u8 o:1,
gra:2,
dir:1,
hwid:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 p:1,
ft:5,
hwid_upper:2;
__u8 hwid:4,
dir:1,
gra:2,
o:1;
#else
#error "Please fix <asm/byteorder.h>"
#endif
};
struct erspan_metadata {
int version;
union {
__be32 index; /* Version 1 (type II)*/
struct erspan_md2 md2; /* Version 2 (type III) */
} u;
};
#define ERSPAN_VERSION 0x1 /* ERSPAN type II */
#define VER_MASK 0xf000
#define VLAN_MASK 0x0fff
#define COS_MASK 0xe000
@@ -38,6 +93,19 @@
#define ID_MASK 0x03ff
#define INDEX_MASK 0xfffff
#define ERSPAN_VERSION2 0x2 /* ERSPAN type III*/
#define BSO_MASK EN_MASK
#define SGT_MASK 0xffff0000
#define P_MASK 0x8000
#define FT_MASK 0x7c00
#define HWID_MASK 0x03f0
#define DIR_MASK 0x0008
#define GRA_MASK 0x0006
#define O_MASK 0x0001
#define HWID_OFFSET 4
#define DIR_OFFSET 3
enum erspan_encap_type {
ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */
ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */
@@ -45,19 +113,71 @@ enum erspan_encap_type {
ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */
};
struct erspan_metadata {
__be32 index; /* type II */
#define ERSPAN_V1_MDSIZE 4
#define ERSPAN_V2_MDSIZE 8
struct erspan_base_hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 vlan_upper:4,
ver:4;
__u8 vlan:8;
__u8 session_id_upper:2,
t:1,
en:2,
cos:3;
__u8 session_id:8;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 ver: 4,
vlan_upper:4;
__u8 vlan:8;
__u8 cos:3,
en:2,
t:1,
session_id_upper:2;
__u8 session_id:8;
#else
#error "Please fix <asm/byteorder.h>"
#endif
};
struct erspanhdr {
__be16 ver_vlan;
#define VER_OFFSET 12
__be16 session_id;
#define COS_OFFSET 13
#define EN_OFFSET 11
#define T_OFFSET 10
struct erspan_metadata md;
};
static inline void set_session_id(struct erspan_base_hdr *ershdr, u16 id)
{
ershdr->session_id = id & 0xff;
ershdr->session_id_upper = (id >> 8) & 0x3;
}
static inline u16 get_session_id(const struct erspan_base_hdr *ershdr)
{
return (ershdr->session_id_upper << 8) + ershdr->session_id;
}
static inline void set_vlan(struct erspan_base_hdr *ershdr, u16 vlan)
{
ershdr->vlan = vlan & 0xff;
ershdr->vlan_upper = (vlan >> 8) & 0xf;
}
static inline u16 get_vlan(const struct erspan_base_hdr *ershdr)
{
return (ershdr->vlan_upper << 8) + ershdr->vlan;
}
static inline void set_hwid(struct erspan_md2 *md2, u8 hwid)
{
md2->hwid = hwid & 0xf;
md2->hwid_upper = (hwid >> 4) & 0x3;
}
static inline u8 get_hwid(const struct erspan_md2 *md2)
{
return (md2->hwid_upper << 4) + md2->hwid;
}
static inline int erspan_hdr_len(int version)
{
return sizeof(struct erspan_base_hdr) +
(version == 1 ? ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE);
}
static inline u8 tos_to_cos(u8 tos)
{
@@ -69,18 +189,19 @@ static inline u8 tos_to_cos(u8 tos)
}
static inline void erspan_build_header(struct sk_buff *skb,
__be32 id, u32 index,
u32 id, u32 index,
bool truncate, bool is_ipv4)
{
struct ethhdr *eth = eth_hdr(skb);
struct ethhdr *eth = (struct ethhdr *)skb->data;
enum erspan_encap_type enc_type;
struct erspanhdr *ershdr;
struct erspan_base_hdr *ershdr;
struct qtag_prefix {
__be16 eth_type;
__be16 tci;
} *qp;
u16 vlan_tci = 0;
u8 tos;
__be32 *idx;
tos = is_ipv4 ? ip_hdr(skb)->tos :
(ipv6_hdr(skb)->priority << 4) +
@@ -97,17 +218,94 @@ static inline void erspan_build_header(struct sk_buff *skb,
enc_type = ERSPAN_ENCAP_INFRAME;
}
skb_push(skb, sizeof(*ershdr));
ershdr = (struct erspanhdr *)skb->data;
memset(ershdr, 0, sizeof(*ershdr));
skb_push(skb, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
ershdr = (struct erspan_base_hdr *)skb->data;
memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
(ERSPAN_VERSION << VER_OFFSET));
ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
(enc_type << EN_OFFSET & EN_MASK) |
((truncate << T_OFFSET) & T_MASK));
ershdr->md.index = htonl(index & INDEX_MASK);
/* Build base header */
ershdr->ver = ERSPAN_VERSION;
ershdr->cos = tos_to_cos(tos);
ershdr->en = enc_type;
ershdr->t = truncate;
set_vlan(ershdr, vlan_tci);
set_session_id(ershdr, id);
/* Build metadata */
idx = (__be32 *)(ershdr + 1);
*idx = htonl(index & INDEX_MASK);
}
/* ERSPAN GRA: timestamp granularity
* 00b --> granularity = 100 microseconds
* 01b --> granularity = 100 nanoseconds
* 10b --> granularity = IEEE 1588
* Here we only support 100 microseconds.
*/
static inline __be32 erspan_get_timestamp(void)
{
u64 h_usecs;
ktime_t kt;
kt = ktime_get_real();
h_usecs = ktime_divns(kt, 100 * NSEC_PER_USEC);
/* ERSPAN base header only has 32-bit,
* so it wraps around 4 days.
*/
return htonl((u32)h_usecs);
}
static inline void erspan_build_header_v2(struct sk_buff *skb,
u32 id, u8 direction, u16 hwid,
bool truncate, bool is_ipv4)
{
struct ethhdr *eth = (struct ethhdr *)skb->data;
struct erspan_base_hdr *ershdr;
struct erspan_md2 *md2;
struct qtag_prefix {
__be16 eth_type;
__be16 tci;
} *qp;
u16 vlan_tci = 0;
u8 gra = 0; /* 100 usec */
u8 bso = 0; /* Bad/Short/Oversized */
u8 sgt = 0;
u8 tos;
tos = is_ipv4 ? ip_hdr(skb)->tos :
(ipv6_hdr(skb)->priority << 4) +
(ipv6_hdr(skb)->flow_lbl[0] >> 4);
/* Unlike v1, v2 does not have En field,
* so only extract vlan tci field.
*/
if (eth->h_proto == htons(ETH_P_8021Q)) {
qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
vlan_tci = ntohs(qp->tci);
}
skb_push(skb, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
ershdr = (struct erspan_base_hdr *)skb->data;
memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
/* Build base header */
ershdr->ver = ERSPAN_VERSION2;
ershdr->cos = tos_to_cos(tos);
ershdr->en = bso;
ershdr->t = truncate;
set_vlan(ershdr, vlan_tci);
set_session_id(ershdr, id);
/* Build metadata */
md2 = (struct erspan_md2 *)(ershdr + 1);
md2->timestamp = erspan_get_timestamp();
md2->sgt = htons(sgt);
md2->p = 1;
md2->ft = 0;
md2->dir = direction;
md2->gra = gra;
md2->o = 0;
set_hwid(md2, hwid);
}
#endif

View File

@@ -15,6 +15,23 @@ static inline int rpl_ipgre_init(void)
static inline void rpl_ipgre_fini(void)
{}
static inline int rpl_ip6gre_init(void)
{
return 0;
}
static inline void rpl_ip6gre_fini(void)
{}
static inline int rpl_ip6_tunnel_init(void)
{
return 0;
}
static inline void rpl_ip6_tunnel_cleanup(void)
{
}
#define gre_fb_xmit dev_queue_xmit
#ifdef CONFIG_INET
@@ -132,6 +149,10 @@ void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
int rpl_ipgre_init(void);
void rpl_ipgre_fini(void);
int rpl_ip6gre_init(void);
void rpl_ip6gre_fini(void);
int rpl_ip6_tunnel_init(void);
void rpl_ip6_tunnel_cleanup(void);
#define gretap_fb_dev_create rpl_gretap_fb_dev_create
struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name,
@@ -147,6 +168,10 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb);
#define ipgre_init rpl_ipgre_init
#define ipgre_fini rpl_ipgre_fini
#define ip6gre_init rpl_ip6gre_init
#define ip6gre_fini rpl_ip6gre_fini
#define ip6_tunnel_init rpl_ip6_tunnel_init
#define ip6_tunnel_cleanup rpl_ip6_tunnel_cleanup
#define gre_fill_metadata_dst ovs_gre_fill_metadata_dst
int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);

View File

@@ -1,14 +1,208 @@
#ifndef _NET_IP6_TUNNEL_WRAPER_H
#define _NET_IP6_TUNNEL_WRAPER_H
#ifndef NET_IP6_TUNNEL_WRAPPER_H
#define NET_IP6_TUNNEL_WRAPPER_H 1
#ifdef HAVE_IP6_TNL_PARM_ERSPAN_VER
#include_next <net/ip6_tunnel.h>
#else
#include <linux/ipv6.h>
#include <linux/netdevice.h>
#include <linux/if_tunnel.h>
#include <linux/ip6_tunnel.h>
#include_next <net/ip6_tunnel.h>
#include <net/ip_tunnels.h>
#include <net/dst_cache.h>
#include <net/dst_metadata.h>
#include "gso.h"
#define ip6tunnel_xmit rpl_ip6tunnel_xmit
void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev);
#define IP6TUNNEL_ERR_TIMEO (30*HZ)
/* capable of sending packets */
#define IP6_TNL_F_CAP_XMIT 0x10000
/* capable of receiving packets */
#define IP6_TNL_F_CAP_RCV 0x20000
/* determine capability on a per-packet basis */
#define IP6_TNL_F_CAP_PER_PACKET 0x40000
#ifndef IP6_TNL_F_ALLOW_LOCAL_REMOTE
#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0
#endif
struct rpl__ip6_tnl_parm {
char name[IFNAMSIZ]; /* name of tunnel device */
int link; /* ifindex of underlying L2 interface */
__u8 proto; /* tunnel protocol */
__u8 encap_limit; /* encapsulation limit for tunnel */
__u8 hop_limit; /* hop limit for tunnel */
bool collect_md;
__be32 flowinfo; /* traffic class and flowlabel for tunnel */
__u32 flags; /* tunnel flags */
struct in6_addr laddr; /* local tunnel end-point address */
struct in6_addr raddr; /* remote tunnel end-point address */
__be16 i_flags;
__be16 o_flags;
__be32 i_key;
__be32 o_key;
__u32 fwmark;
__u32 index; /* ERSPAN type II index */
__u8 erspan_ver; /* ERSPAN version */
__u8 dir; /* direction */
__u16 hwid; /* hwid */
};
#define __ip6_tnl_parm rpl__ip6_tnl_parm
/* IPv6 tunnel */
struct rpl_ip6_tnl {
struct rpl_ip6_tnl __rcu *next; /* next tunnel in list */
struct net_device *dev; /* virtual device associated with tunnel */
struct net *net; /* netns for packet i/o */
struct __ip6_tnl_parm parms; /* tunnel configuration parameters */
struct flowi fl; /* flowi template for xmit */
struct dst_cache dst_cache; /* cached dst */
struct gro_cells gro_cells;
int err_count;
unsigned long err_time;
/* These fields used only by GRE */
__u32 i_seqno; /* The last seen seqno */
__u32 o_seqno; /* The last output seqno */
int hlen; /* tun_hlen + encap_hlen */
int tun_hlen; /* Precalculated header length */
int encap_hlen; /* Encap header length (FOU,GUE) */
struct ip_tunnel_encap encap;
int mlink;
};
#define ip6_tnl rpl_ip6_tnl
struct rpl_ip6_tnl_encap_ops {
size_t (*encap_hlen)(struct ip_tunnel_encap *e);
int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e,
u8 *protocol, struct flowi6 *fl6);
};
#define ip6_tnl_encap_ops rpl_ip6_tnl_encap_ops
#ifdef CONFIG_INET
#ifndef MAX_IPTUN_ENCAP_OPS
#define MAX_IPTUN_ENCAP_OPS 8
#endif
extern const struct ip6_tnl_encap_ops __rcu *
rpl_ip6tun_encaps[MAX_IPTUN_ENCAP_OPS];
int rpl_ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops,
unsigned int num);
#define ip6_tnl_encap_add_ops rpl_ip6_tnl_encap_add_ops
int rpl_ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops,
unsigned int num);
#define ip6_tnl_encap_del_ops rpl_ip6_tnl_encap_del_ops
int rpl_ip6_tnl_encap_setup(struct ip6_tnl *t,
struct ip_tunnel_encap *ipencap);
#define ip6_tnl_encap_setup rpl_ip6_tnl_encap_setup
#ifndef HAVE_TUNNEL_ENCAP_TYPES
enum tunnel_encap_types {
TUNNEL_ENCAP_NONE,
TUNNEL_ENCAP_FOU,
TUNNEL_ENCAP_GUE,
};
#endif
static inline int ip6_encap_hlen(struct ip_tunnel_encap *e)
{
const struct ip6_tnl_encap_ops *ops;
int hlen = -EINVAL;
if (e->type == TUNNEL_ENCAP_NONE)
return 0;
if (e->type >= MAX_IPTUN_ENCAP_OPS)
return -EINVAL;
rcu_read_lock();
ops = rcu_dereference(rpl_ip6tun_encaps[e->type]);
if (likely(ops && ops->encap_hlen))
hlen = ops->encap_hlen(e);
rcu_read_unlock();
return hlen;
}
static inline int ip6_tnl_encap(struct sk_buff *skb, struct ip6_tnl *t,
u8 *protocol, struct flowi6 *fl6)
{
const struct ip6_tnl_encap_ops *ops;
int ret = -EINVAL;
if (t->encap.type == TUNNEL_ENCAP_NONE)
return 0;
if (t->encap.type >= MAX_IPTUN_ENCAP_OPS)
return -EINVAL;
rcu_read_lock();
ops = rcu_dereference(rpl_ip6tun_encaps[t->encap.type]);
if (likely(ops && ops->build_header))
ret = ops->build_header(skb, &t->encap, protocol, fl6);
rcu_read_unlock();
return ret;
}
/* Tunnel encapsulation limit destination sub-option */
struct ipv6_tlv_tnl_enc_lim {
__u8 type; /* type-code for option */
__u8 length; /* option length */
__u8 encap_limit; /* tunnel encapsulation limit */
} __packed;
int rpl_ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
#define ip6_tnl_rcv_ctl rpl_ip6_tnl_rcv_ctl
int rpl_ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
const struct tnl_ptk_info *tpi,
struct metadata_dst *tun_dst,
bool log_ecn_error);
#define ip6_tnl_rcv rpl_ip6_tnl_rcv
int rpl_ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
#define ip6_tnl_xmit_ctl rpl_ip6_tnl_xmit_ctl
int rpl_ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
struct flowi6 *fl6, int encap_limit, __u32 *pmtu,
__u8 proto);
#define ip6_tnl_xmit rpl_ip6_tnl_xmit
__u16 rpl_ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
#define ip6_tnl_parse_tlv_enc_lim rpl_ip6_tnl_parse_tlv_enc_lim
__u32 rpl_ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
#define ip6_tnl_get_cap rpl_ip6_tnl_get_cap
struct net *rpl_ip6_tnl_get_link_net(const struct net_device *dev);
#define ip6_tnl_get_link_net rpl_ip6_tnl_get_link_net
int rpl_ip6_tnl_get_iflink(const struct net_device *dev);
#define ip6_tnl_get_iflink rpl_ip6_tnl_get_iflink
int rpl_ip6_tnl_change_mtu(struct net_device *dev, int new_mtu);
#define ip6_tnl_change_mtu rpl_ip6_tnl_change_mtu
static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev)
{
int pkt_len, err;
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
pkt_len = skb->len - skb_inner_network_offset(skb);
err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
if (unlikely(net_xmit_eval(err)))
pkt_len = -1;
iptunnel_xmit_stats(dev, pkt_len);
}
#endif
#endif /* HAVE_IP6_TNL_PARM_ERSPAN_VER */
#endif

View File

@@ -39,6 +39,35 @@ static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
}
#ifndef HAVE_IP6_MAKE_FLOWLABEL_FL6
#define ip6_make_flowlabel rpl_ip6_make_flowlabel
static inline __be32 rpl_ip6_make_flowlabel(struct net *net,
struct sk_buff *skb,
__be32 flowlabel, bool autolabel,
struct flowi6 *fl6)
{
#ifndef HAVE_NETNS_SYSCTL_IPV6_AUTO_FLOWLABELS
if (!flowlabel && autolabel) {
#else
if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) {
#endif
u32 hash;
hash = skb_get_hash(skb);
/* Since this is being sent on the wire obfuscate hash a bit
* to minimize possbility that any useful information to an
* attacker is leaked. Only lower 20 bits are relevant.
*/
hash ^= hash >> 12;
flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK;
}
return flowlabel;
}
#endif
#ifndef IPV6_TCLASS_SHIFT
#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
#define IPV6_TCLASS_SHIFT 20

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -196,6 +196,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
struct ip_tunnel_net *itn;
struct ip_tunnel *tunnel;
const struct iphdr *iph;
struct erspan_md2 *md2;
int ver;
int len;

View File

@@ -67,6 +67,12 @@ int ovs_vport_init(void)
err = ipgre_init();
if (err)
goto err_gre;
err = ip6gre_init();
if (err)
goto err_ip6gre;
err = ip6_tunnel_init();
if (err)
goto err_ip6_tunnel;
err = geneve_init_module();
if (err)
goto err_geneve;
@@ -84,6 +90,10 @@ err_stt:
err_vxlan:
geneve_cleanup_module();
err_geneve:
ip6_tunnel_cleanup();
err_ip6_tunnel:
ip6gre_fini();
err_ip6gre:
ipgre_fini();
err_gre:
lisp_cleanup_module();
@@ -102,6 +112,8 @@ void ovs_vport_exit(void)
ovs_stt_cleanup_module();
vxlan_cleanup_module();
geneve_cleanup_module();
ip6_tunnel_cleanup();
ip6gre_fini();
ipgre_fini();
lisp_cleanup_module();
kfree(dev_table);

View File

@@ -90,6 +90,9 @@ vport_type_to_kind(enum ovs_vport_type type,
case OVS_VPORT_TYPE_VXLAN:
return "vxlan";
case OVS_VPORT_TYPE_GRE:
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L3) {
return "gre";
} else if (tnl_cfg->pt_mode == NETDEV_PT_LEGACY_L2) {
@@ -262,6 +265,9 @@ dpif_netlink_rtnl_verify(const struct netdev_tunnel_config *tnl_cfg,
case OVS_VPORT_TYPE_INTERNAL:
case OVS_VPORT_TYPE_LISP:
case OVS_VPORT_TYPE_STT:
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
case OVS_VPORT_TYPE_UNSPEC:
case __OVS_VPORT_TYPE_MAX:
default:
@@ -316,6 +322,9 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg,
nl_msg_put_be16(&request, IFLA_VXLAN_PORT, tnl_cfg->dst_port);
break;
case OVS_VPORT_TYPE_GRE:
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
nl_msg_put_flag(&request, IFLA_GRE_COLLECT_METADATA);
break;
case OVS_VPORT_TYPE_GENEVE:
@@ -438,6 +447,9 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type)
case OVS_VPORT_TYPE_INTERNAL:
case OVS_VPORT_TYPE_LISP:
case OVS_VPORT_TYPE_STT:
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
case OVS_VPORT_TYPE_UNSPEC:
case __OVS_VPORT_TYPE_MAX:
default:

View File

@@ -787,6 +787,11 @@ get_vport_type(const struct dpif_netlink_vport *vport)
case OVS_VPORT_TYPE_STT:
return "stt";
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
return "";
case OVS_VPORT_TYPE_UNSPEC:
case __OVS_VPORT_TYPE_MAX:
break;

View File

@@ -3377,6 +3377,9 @@ propagate_tunnel_data_to_flow(struct xlate_ctx *ctx, struct eth_addr dmac,
switch (tnl_type) {
case OVS_VPORT_TYPE_GRE:
case OVS_VPORT_TYPE_ERSPAN:
case OVS_VPORT_TYPE_IP6ERSPAN:
case OVS_VPORT_TYPE_IP6GRE:
nw_proto = IPPROTO_GRE;
break;
case OVS_VPORT_TYPE_VXLAN: