- BUILD_ENV="-m32" OPTS="--disable-ssl"
- KERNEL=3.16.54 DPDK=1
- KERNEL=3.16.54 DPDK=1 OPTS="--enable-shared"
- - KERNEL=4.15.3
- - KERNEL=4.14.19
- - KERNEL=4.9.81
- - KERNEL=4.4.115
- - KERNEL=4.1.49
- - KERNEL=3.10.108
+ - KERNEL=4.14.47
+ - KERNEL=4.9.105
+ - KERNEL=4.4.135
+ - KERNEL=4.1.52
+ - KERNEL=3.16.56
- TESTSUITE=1 LIBS=-ljemalloc
matrix:
AC_MSG_RESULT([$kversion])
if test "$version" -ge 4; then
- if test "$version" = 4 && test "$patchlevel" -le 15; then
+ if test "$version" = 4 && test "$patchlevel" -le 14; then
: # Linux 4.x
else
- AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.15.x is not supported (please refer to the FAQ for advice)])
+ AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.14.x is not supported (please refer to the FAQ for advice)])
fi
elif test "$version" = 3 && test "$patchlevel" -ge 10; then
: # Linux 3.x
OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netdevice.h], [net_device],
[max_mtu],
[OVS_DEFINE([HAVE_NET_DEVICE_MAX_MTU])])
- OVS_GREP_IFELSE([$KSRC/include/net/erspan.h],
- [__LINUX_ERSPAN_H],
- [OVS_DEFINE([HAVE_LINUX_ERSPAN_H])])
- OVS_FIND_PARAM_IFELSE([$KSRC/net/ipv6/ip6_gre.c],
- [ip6gre_tunnel_validate], [extack],
- [OVS_DEFINE([HAVE_IP6GRE_EXTACK])])
OVS_FIND_FIELD_IFELSE([$KSRC/include/net/ip6_tunnel.h], [__ip6_tnl_parm],
[erspan_ver],
[OVS_DEFINE([HAVE_IP6_TNL_PARM_ERSPAN_VER])])
OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
[IFLA_IPTUN_COLLECT_METADATA],
[OVS_DEFINE([HAVE_IFLA_IPTUN_COLLECT_METADATA])])
- OVS_GREP_IFELSE([$KSRC/net/ipv4/gre_demux.c],
- [parse_gre_header],
- [OVS_DEFINE([HAVE_DEMUX_PARSE_GRE_HEADER])])
OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
[IFLA_GRE_ENCAP_DPORT])
OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
[IFLA_GRE_ERSPAN_INDEX])
OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
[IFLA_GRE_ERSPAN_HWID])
+ OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
+ [IFLA_IPTUN_FWMARK])
if cmp -s datapath/linux/kcompat.h.new \
datapath/linux/kcompat.h >/dev/null 2>&1; then
dev->netdev_ops = &geneve_netdev_ops;
dev->ethtool_ops = &geneve_ethtool_ops;
+#ifndef HAVE_NEEDS_FREE_NETDEV
dev->destructor = free_netdev;
+#else
+ dev->needs_free_netdev = true;
+#endif
SET_NETDEV_DEVTYPE(dev, &geneve_type);
[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
};
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int geneve_validate(struct nlattr *tb[], struct nlattr *data[])
+#endif
{
if (tb[IFLA_ADDRESS]) {
if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
return 0;
}
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int geneve_newlink(struct net *net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int geneve_newlink(struct net *net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
+#endif
{
__be16 dst_port = htons(GENEVE_UDP_PORT);
__u8 ttl = 0, tos = 0;
return addend;
}
-#ifndef HAVE_GRE_HANDLE_OFFLOADS
-#ifndef HAVE_GRE_CISCO_REGISTER
-
-#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
-static __sum16 check_checksum(struct sk_buff *skb)
-{
- __sum16 csum = 0;
-
- switch (skb->ip_summed) {
- case CHECKSUM_COMPLETE:
- csum = csum_fold(skb->csum);
-
- if (!csum)
- break;
- /* Fall through. */
-
- case CHECKSUM_NONE:
- skb->csum = 0;
- csum = __skb_checksum_complete(skb);
- skb->ip_summed = CHECKSUM_COMPLETE;
- break;
- }
-
- return csum;
-}
-
-static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
- bool *csum_err)
-{
- unsigned int ip_hlen = ip_hdrlen(skb);
- struct gre_base_hdr *greh;
- __be32 *options;
- int hdr_len;
-
- if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr))))
- return -EINVAL;
-
- greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
- if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING)))
- return -EINVAL;
-
- tpi->flags = gre_flags_to_tnl_flags(greh->flags);
- hdr_len = ip_gre_calc_hlen(tpi->flags);
- tpi->hdr_len = hdr_len;
- tpi->proto = greh->protocol;
-
- if (!pskb_may_pull(skb, hdr_len))
- return -EINVAL;
-
- options = (__be32 *)(greh + 1);
- if (greh->flags & GRE_CSUM) {
- if (check_checksum(skb)) {
- *csum_err = true;
- return -EINVAL;
- }
- options++;
- }
-
- if (greh->flags & GRE_KEY) {
- tpi->key = *options;
- options++;
- } else
- tpi->key = 0;
-
- if (unlikely(greh->flags & GRE_SEQ)) {
- tpi->seq = *options;
- options++;
- } else
- tpi->seq = 0;
-
- /* WCCP version 1 and 2 protocol decoding.
- * - Change protocol to IP
- * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
- */
- if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
- tpi->proto = htons(ETH_P_IP);
- if ((*(u8 *)options & 0xF0) != 0x40) {
- hdr_len += 4;
- if (!pskb_may_pull(skb, hdr_len))
- return -EINVAL;
- }
- }
-
- return iptunnel_pull_header(skb, hdr_len, tpi->proto, false);
-}
-
-static struct gre_cisco_protocol __rcu *gre_cisco_proto;
-static int gre_cisco_rcv(struct sk_buff *skb)
-{
- struct gre_cisco_protocol *proto;
- struct tnl_ptk_info tpi;
- bool csum_err = false;
-
- rcu_read_lock();
- proto = rcu_dereference(gre_cisco_proto);
- if (!proto)
- goto drop;
-
- if (parse_gre_header(skb, &tpi, &csum_err) < 0)
- goto drop;
- proto->handler(skb, &tpi);
- rcu_read_unlock();
- return 0;
-
-drop:
- rcu_read_unlock();
- kfree_skb(skb);
- return 0;
-}
-
-static const struct gre_protocol ipgre_protocol = {
- .handler = gre_cisco_rcv,
-};
-
-int rpl_gre_cisco_register(struct gre_cisco_protocol *newp)
-{
- int err;
-
- err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
- if (err) {
- pr_warn("%s: cannot register gre_cisco protocol handler\n", __func__);
- return err;
- }
-
-
- return (cmpxchg((struct gre_cisco_protocol **)&gre_cisco_proto, NULL, newp) == NULL) ?
- 0 : -EBUSY;
-}
-EXPORT_SYMBOL_GPL(rpl_gre_cisco_register);
-
-int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto)
-{
- int ret;
- ret = (cmpxchg((struct gre_cisco_protocol **)&gre_cisco_proto, proto, NULL) == proto) ?
- 0 : -EINVAL;
-
- if (ret)
- return ret;
-
- synchronize_net();
- ret = gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
- return ret;
-}
-EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister);
-
-#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */
-#endif /* !HAVE_GRE_CISCO_REGISTER */
-#endif
-
void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
int hdr_len)
{
#ifndef __LINUX_COMPILER_H
+#if 0
+/* Disable this check - it no longer makes sense with so many backports
+ * due to spectre mitigation
+ */
#ifndef HAVE_LINUX_COMPILER_TYPES_H
#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
#endif
#endif
+#endif
#include_next <linux/compiler-gcc.h>
void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb,
struct metadata_dst *tun_dst);
-#ifndef HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE
static inline struct metadata_dst *
rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t flags)
{
return metadata_dst_alloc(optslen, flags);
}
#define metadata_dst_alloc rpl_metadata_dst_alloc
-#endif
#endif /* __NET_DST_METADATA_WRAPPER_H */
-#ifndef HAVE_LINUX_ERSPAN_H
+#ifndef USE_UPSTREAM_TUNNEL
#ifndef __LINUX_ERSPAN_H
#define __LINUX_ERSPAN_H
return flags;
}
-#ifndef HAVE_GRE_CISCO_REGISTER
-
-/* GRE demux not available, implement our own demux. */
-#define MAX_GRE_PROTO_PRIORITY 255
-
-struct gre_cisco_protocol {
- int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi);
- int (*err_handler)(struct sk_buff *skb, u32 info,
- const struct tnl_ptk_info *tpi);
- u8 priority;
-};
-
-#define gre_cisco_register rpl_gre_cisco_register
-int rpl_gre_cisco_register(struct gre_cisco_protocol *proto);
-
-#define gre_cisco_unregister rpl_gre_cisco_unregister
-int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto);
-
-#ifndef GRE_HEADER_SECTION
-struct gre_base_hdr {
- __be16 flags;
- __be16 protocol;
-};
-#define GRE_HEADER_SECTION 4
-#endif
-
-#endif /* HAVE_GRE_CISCO_REGISTER */
-
#define gre_build_header rpl_gre_build_header
void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
int hdr_len);
* rpl prefix is to make OVS build happy.
*/
#define iptunnel_handle_offloads rpl_iptunnel_handle_offloads
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
bool csum_help,
int gso_type_mask);
+#else
+int rpl_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help,
+ int gso_type_mask);
+#endif
#define iptunnel_xmit rpl_iptunnel_xmit
void rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
#define ip_tunnel_collect_metadata() true
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0)
#undef TUNNEL_NOCACHE
#define TUNNEL_NOCACHE 0
return true;
}
-#endif
#define ip_tunnel_dst rpl_ip_tunnel_dst
struct rpl_ip_tunnel_dst {
return ret;
}
-#ifndef HAVE_PCPU_SW_NETSTATS
#define ip_tunnel_get_stats64 rpl_ip_tunnel_get_stats64
-#else
-#define rpl_ip_tunnel_get_stats64 ip_tunnel_get_stats64
-#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)
struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot);
-
+#else
+void rpl_ip_tunnel_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot);
+#endif
#define ip_tunnel_get_dsfield rpl_ip_tunnel_get_dsfield
static inline u8 rpl_ip_tunnel_get_dsfield(const struct iphdr *iph,
const struct sk_buff *skb)
#else
static int gre_handle_offloads(struct sk_buff *skb, bool csum)
{
- return iptunnel_handle_offloads(skb,
+ return iptunnel_handle_offloads(skb, csum,
csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
-
+}
#endif
static void prepare_ip6gre_xmit_ipv4(struct sk_buff *skb,
.ndo_start_xmit = ip6gre_tunnel_xmit,
.ndo_do_ioctl = ip6gre_tunnel_ioctl,
.ndo_change_mtu = ip6_tnl_change_mtu,
- .ndo_get_stats64 = rpl_ip_tunnel_get_stats64,
+ .ndo_get_stats64 = ip_tunnel_get_stats64,
#ifdef HAVE_NDO_GET_IFLINK
.ndo_get_iflink = ip6_tnl_get_iflink,
#endif
.id = &ip6gre_net_id,
.size = sizeof(struct ip6gre_net),
};
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6gre_tunnel_validate(struct nlattr *tb[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
}
#define ip6gre_tunnel_validate rpl_ip6gre_tunnel_validate
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
#else
}
out:
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
return ip6gre_tunnel_validate(tb, data, extack);
#else
return ip6gre_tunnel_validate(tb, data);
}
#define ip6gre_tap_validate rpl_ip6gre_tap_validate
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6erspan_tap_validate(struct nlattr *tb[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
if (!data)
return 0;
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
ret = ip6gre_tap_validate(tb, data, extack);
#else
ret = ip6gre_tap_validate(tb, data);
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ip6_tnl_change_mtu,
- .ndo_get_stats64 = rpl_ip_tunnel_get_stats64,
+ .ndo_get_stats64 = ip_tunnel_get_stats64,
#ifdef HAVE_NDO_GET_IFLINK
.ndo_get_iflink = ip6_tnl_get_iflink,
#endif
return ret;
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6gre_newlink_common(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
}
#define ip6gre_newlink_common rpl_ip6gre_newlink_common
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6gre_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
return -EEXIST;
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
err = ip6gre_newlink_common(src_net, dev, tb, data, extack);
#else
err = ip6gre_newlink_common(src_net, dev, tb, data);
#define ip6gre_newlink rpl_ip6gre_newlink
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static struct ip6_tnl *
rpl_ip6gre_changelink_common(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[], struct __ip6_tnl_parm *p_p,
}
#define ip6gre_changelink_common rpl_ip6gre_changelink_common
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
struct __ip6_tnl_parm p;
struct ip6_tnl *t;
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
t = ip6gre_changelink_common(dev, tb, data, &p, extack);
#else
t = ip6gre_changelink_common(dev, tb, data, &p);
netif_keep_dst(dev);
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6erspan_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
return -EEXIST;
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
err = ip6gre_newlink_common(src_net, dev, tb, data, extack);
#else
err = ip6gre_newlink_common(src_net, dev, tb, data);
return 0;
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6erspan_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id);
struct __ip6_tnl_parm p;
struct ip6_tnl *t;
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
t = ip6gre_changelink_common(dev, tb, data, &p, extack);
#else
t = ip6gre_changelink_common(dev, tb, data, &p);
t = netdev_priv(dev);
t->parms.collect_md = true;
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+ err = ip6erspan_newlink(net, dev, tb, NULL, NULL);
+#else
err = ip6erspan_newlink(net, dev, tb, NULL);
+#endif
if (err < 0) {
free_netdev(dev);
return ERR_PTR(err);
t = netdev_priv(dev);
t->parms.collect_md = true;
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+ err = ip6gre_newlink(net, dev, tb, NULL, NULL);
+#else
err = ip6gre_newlink(net, dev, tb, NULL);
+#endif
if (err < 0) {
free_netdev(dev);
return ERR_PTR(err);
IFLA_IPTUN_ENCAP_SPORT,
IFLA_IPTUN_ENCAP_DPORT,
#endif
-#ifndef HAVE_IFLA_IPTUN_COLLECT_METADTA
+#ifndef HAVE_IFLA_IPTUN_COLLECT_METADATA
IFLA_IPTUN_COLLECT_METADATA = IFLA_IPTUN_ENCAP_DPORT + 1,
- IFLA_IPTUN_FWMARK,
+#endif
+#ifndef HAVE_IFLA_IPTUN_FWMARK
+ IFLA_IPTUN_FWMARK = IFLA_IPTUN_COLLECT_METADATA + 1,
#endif
RPL__IFLA_IPTUN_MAX = IFLA_IPTUN_FWMARK + 1,
};
}
#define iptunnel_handle_offloads rpl__iptunnel_handle_offloads
-static int rpl__iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum)
+static int rpl__iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
+ int __always_unused ignored)
{
int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE;
gso_fix_segment_t fix_segment;
// FIX ME
// fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
- if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+ if (iptunnel_handle_offloads(skb, true, SKB_GSO_IPXIP6))
return -1;
dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
// FIX ME
// fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
- if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+ if (iptunnel_handle_offloads(skb, true, SKB_GSO_IPXIP6))
return -1;
dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
return 0;
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
#else
return ret;
}
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
}
#define ip6_tnl_newlink rpl_ip6_tnl_newlink
-#ifdef HAVE_IP6GRE_EXTACK
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
static int rpl_ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[],
struct netlink_ext_ack *extack)
#include <linux/kernel.h>
#include <linux/kconfig.h>
#include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/netdev_features.h>
#endif
}
-#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
-/* Called with rcu_read_lock and BH disabled. */
-static int gre_err(struct sk_buff *skb, u32 info,
- const struct tnl_ptk_info *tpi)
-{
- return PACKET_REJECT;
-}
-#endif
static struct dst_ops md_dst_ops = {
.family = AF_UNSPEC,
};
ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
}
-#ifndef HAVE_DEMUX_PARSE_GRE_HEADER
static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *unused_tpi)
{
struct tnl_ptk_info tpi;
kfree_skb(skb);
return 0;
}
-#else
-static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *__tpi)
-{
- struct tnl_ptk_info tpi = *__tpi;
-
- if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
- tpi.proto == htons(ETH_P_ERSPAN2))) {
- if (erspan_rcv(skb, &tpi, 0) == PACKET_RCVD)
- return 0;
- goto drop;
- }
-
- if (ipgre_rcv(skb, &tpi, 0) == PACKET_RCVD)
- return 0;
-drop:
-
- kfree_skb(skb);
- return 0;
-}
-#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+#include "gso.h"
/* gre_handle_offloads() has different return type on older kernsl. */
static void gre_nop_fix(struct sk_buff *skb) { }
skb->len - gre_offset, 0));
}
-static bool is_gre_gso(struct sk_buff *skb)
-{
- return skb_is_gso(skb);
-}
-
#define gre_handle_offloads rpl_gre_handle_offloads
static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
{
return ovs_iptunnel_handle_offloads(skb, type, fix_segment);
}
#else
+static int gre_handle_offloads(struct sk_buff *skb, bool csum)
+{
+ return iptunnel_handle_offloads(skb, csum,
+ csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
+}
+#endif
static bool is_gre_gso(struct sk_buff *skb)
{
(SKB_GSO_GRE | SKB_GSO_GRE_CSUM);
}
-static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
-{
- if (skb_is_gso(skb) && skb_is_encapsulated(skb))
- return -ENOSYS;
-
-#undef gre_handle_offloads
- return gre_handle_offloads(skb, gre_csum);
-}
-#endif
-
static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags,
__be16 proto, __be32 key, __be32 seq)
{
goto err_free_rt;
}
- skb = vlan_hwaccel_push_inside(skb);
+ skb = __vlan_hwaccel_push_inside(skb);
if (unlikely(!skb)) {
err = -ENOMEM;
goto err_free_rt;
}
/* Push Tunnel header. */
- err = rpl_gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM));
+ err = gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM));
if (err)
goto err_free_rt;
}
}
-#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
-static struct gre_cisco_protocol ipgre_cisco_protocol = {
- .handler = gre_rcv,
- .err_handler = gre_err,
- .priority = 1,
-};
-#endif
-
static int __gre_rcv(struct sk_buff *skb)
{
return gre_rcv(skb, NULL);
.size = sizeof(struct ip_tunnel_net),
};
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
+#endif
{
__be16 flags;
return 0;
}
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
+#endif
{
__be32 daddr;
}
out:
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+ return ipgre_tunnel_validate(tb, data, NULL);
+#else
return ipgre_tunnel_validate(tb, data);
+#endif
}
enum {
#define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1)
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int erspan_validate(struct nlattr *tb[], struct nlattr *data[])
+#endif
{
__be16 flags = 0;
int ret;
if (!data)
return 0;
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+ ret = ipgre_tap_validate(tb, data, NULL);
+#else
ret = ipgre_tap_validate(tb, data);
+#endif
if (ret)
return ret;
#else
.ndo_change_mtu = ip_tunnel_change_mtu,
#endif
- .ndo_get_stats64 = rpl_ip_tunnel_get_stats64,
+ .ndo_get_stats64 = ip_tunnel_get_stats64,
#ifdef HAVE_NDO_GET_IFLINK
.ndo_get_iflink = rpl_ip_tunnel_get_iflink,
#endif
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ip_tunnel_change_mtu,
- .ndo_get_stats64 = rpl_ip_tunnel_get_stats64,
+ .ndo_get_stats64 = ip_tunnel_get_stats64,
#ifdef HAVE_NDO_GET_IFLINK
.ndo_get_iflink = rpl_ip_tunnel_get_iflink,
#endif
ip_tunnel_setup(dev, erspan_net_id);
}
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int ipgre_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int ipgre_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
+#endif
{
struct ip_tunnel_parm p;
int err;
t = netdev_priv(dev);
t->collect_md = true;
/* Configure flow based GRE device. */
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+ err = ipgre_newlink(net, dev, tb, NULL, NULL);
+#else
err = ipgre_newlink(net, dev, tb, NULL);
+#endif
if (err < 0) {
free_netdev(dev);
return ERR_PTR(err);
t = netdev_priv(dev);
t->collect_md = true;
/* Configure flow based GRE device. */
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+ err = ipgre_newlink(net, dev, tb, NULL, NULL);
+#else
err = ipgre_newlink(net, dev, tb, NULL);
+#endif
if (err < 0) {
free_netdev(dev);
return ERR_PTR(err);
if (err < 0)
goto pnet_ipgre_failed;
-#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
- err = gre_cisco_register(&ipgre_cisco_protocol);
- if (err < 0) {
- pr_info("%s: can't add protocol\n", __func__);
- goto add_proto_failed;
- }
-#else
err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
if (err < 0) {
pr_info("%s: can't add protocol\n", __func__);
goto add_proto_failed;
}
-#endif
pr_info("GRE over IPv4 tunneling driver\n");
{
ovs_vport_ops_unregister(&ovs_erspan_vport_ops);
ovs_vport_ops_unregister(&ovs_ipgre_vport_ops);
-#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
- gre_cisco_unregister(&ipgre_cisco_protocol);
-#else
gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
-#endif
unregister_pernet_device(&ipgre_net_ops);
unregister_pernet_device(&erspan_net_ops);
unregister_pernet_device(&ipgre_tap_net_ops);
static void ip_tunnel_dev_free(struct net_device *dev)
{
free_percpu(dev->tstats);
+#ifndef HAVE_NEEDS_FREE_NETDEV
free_netdev(dev);
+#endif
}
void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
}
EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
bool csum_help,
int gso_type_mask)
+#else
+int rpl_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help,
+ int gso_type_mask)
+#endif
{
int err;
if (unlikely(err))
goto error;
skb_shinfo(skb)->gso_type |= gso_type_mask;
- return skb;
+ goto out;
}
/* If packet is not gso and we are resolving any partial checksum,
} else if (skb->ip_summed != CHECKSUM_PARTIAL)
skb->ip_summed = CHECKSUM_NONE;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+out:
return skb;
error:
kfree_skb(skb);
return ERR_PTR(err);
+#else
+out:
+error:
+ return 0;
+#endif
}
EXPORT_SYMBOL_GPL(rpl_iptunnel_handle_offloads);
dst[i] = src[i];
#endif
}
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)
struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot)
+#else
+void rpl_ip_tunnel_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
+#endif
{
int i;
tot->tx_bytes += tx_bytes;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)
return tot;
-}
#endif
+}
void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev)
if (unlikely(err))
goto out_free;
- skb = vlan_hwaccel_push_inside(skb);
+ if (skb_vlan_tag_present(skb))
+ skb = __vlan_hwaccel_push_inside(skb);
if (WARN_ON(!skb))
return -ENOMEM;
eth_hw_addr_random(dev);
ether_setup(dev);
+#ifndef HAVE_NEEDS_FREE_NETDEV
dev->destructor = free_netdev;
+#else
+ dev->needs_free_netdev = true;
+#endif
SET_NETDEV_DEVTYPE(dev, &vxlan_type);
dev->features |= NETIF_F_LLTX;
[IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG },
};
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
+#endif
{
if (tb[IFLA_ADDRESS]) {
if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
return 0;
}
+#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
+static int vxlan_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+#else
static int vxlan_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
+#endif
{
pr_info("unsupported operation\n");
return -EINVAL;