From: Jesse Gross Date: Thu, 3 Dec 2009 02:56:36 +0000 (-0800) Subject: gre: Compatibility with older Linux kernel versions. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db12f2fc076e2d5bb5ae364e217ca2d84c8b0154;p=openvswitch gre: Compatibility with older Linux kernel versions. The upcoming GRE kernel module compiles on a range (2.6.18+) of Linux kernel versions. The module expects the kernel headers to look like newer versions. Where older and newer versions of the kernel differ this commit implements shims to paper over the changes. --- diff --git a/datapath/linux-2.6/compat-2.6/include/linux/if.h b/datapath/linux-2.6/compat-2.6/include/linux/if.h new file mode 100644 index 00000000..0aa9ee35 --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/linux/if.h @@ -0,0 +1,13 @@ +#ifndef __LINUX_IF_WRAPPER_H +#define __LINUX_IF_WRAPPER_H 1 + +#include_next + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + +#define IFF_XMIT_DST_RELEASE 0 + +#endif /* linux kernel < 2.6.31 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/linux/if_ether.h b/datapath/linux-2.6/compat-2.6/include/linux/if_ether.h new file mode 100644 index 00000000..b8390e23 --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/linux/if_ether.h @@ -0,0 +1,13 @@ +#ifndef __LINUX_IF_ETHER_WRAPPER_H +#define __LINUX_IF_ETHER_WRAPPER_H 1 + +#include_next + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + +#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ + +#endif /* linux kernel < 2.6.28 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/linux/in.h b/datapath/linux-2.6/compat-2.6/include/linux/in.h new file mode 100644 index 00000000..2cfe6450 --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/linux/in.h @@ -0,0 +1,16 @@ +#ifndef __LINUX_IN_WRAPPER_H +#define __LINUX_IN_WRAPPER_H 1 + +#include_next + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + +static inline bool ipv4_is_multicast(__be32 addr) +{ + return (addr & htonl(0xf0000000)) == htonl(0xe0000000); +} + +#endif /* linux kernel < 2.6.25 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/linux/inetdevice.h b/datapath/linux-2.6/compat-2.6/include/linux/inetdevice.h new file mode 100644 index 00000000..813a70ad --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/linux/inetdevice.h @@ -0,0 +1,14 @@ +#ifndef __LINUX_INETDEVICE_WRAPPER_H +#define __LINUX_INETDEVICE_WRAPPER_H 1 + +#include_next + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + +#define inetdev_by_index(net, ifindex) \ + inetdev_by_index((ifindex)) + +#endif /* linux kernel < 2.6.25 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/linux/netdevice.h b/datapath/linux-2.6/compat-2.6/include/linux/netdevice.h index b7182832..c25f2bd0 100644 --- a/datapath/linux-2.6/compat-2.6/include/linux/netdevice.h +++ b/datapath/linux-2.6/compat-2.6/include/linux/netdevice.h @@ -5,6 +5,7 @@ struct net; +#include /* Before 2.6.21, struct net_device has a "struct class_device" member named * class_dev. Beginning with 2.6.21, struct net_device instead has a "struct * device" member named dev. Otherwise the usage of these members is pretty @@ -23,14 +24,36 @@ struct net; static inline struct net *dev_net(const struct net_device *dev) { +#ifdef CONFIG_NET_NS + return dev->nd_net; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + return &init_net; +#else return NULL; +#endif +} + +static inline +void dev_net_set(struct net_device *dev, const struct net *net) +{ +#ifdef CONFIG_NET_NS + dev->nd_dev = net; +#endif } #endif /* linux kernel < 2.6.26 */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#define NETIF_F_NETNS_LOCAL 0 +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) #define proc_net init_net.proc_net #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) +typedef int netdev_tx_t; +#endif + #ifndef for_each_netdev /* Linux before 2.6.22 didn't have for_each_netdev at all. */ #define for_each_netdev(net, d) for (d = dev_base; d; d = d->next) diff --git a/datapath/linux-2.6/compat-2.6/include/linux/skbuff.h b/datapath/linux-2.6/compat-2.6/include/linux/skbuff.h index dd9bfa37..edeba5ae 100644 --- a/datapath/linux-2.6/compat-2.6/include/linux/skbuff.h +++ b/datapath/linux-2.6/compat-2.6/include/linux/skbuff.h @@ -76,6 +76,29 @@ static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom) } #endif /* !HAVE_SKB_COW */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) +static inline int skb_clone_writable(struct sk_buff *skb, int len) +{ + return false; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) +static inline struct dst_entry *skb_dst(const struct sk_buff *skb) +{ + return (struct dst_entry *)skb->dst; +} + +static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst) +{ + skb->dst = dst; +} + +static inline struct rtable *skb_rtable(const struct sk_buff *skb) +{ + return (struct rtable *)skb->dst; +} +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) /* Emulate Linux 2.6.17 and later behavior, in which kfree_skb silently ignores @@ -101,6 +124,7 @@ static inline void kfree_skb_maybe_null(struct sk_buff *skb) #ifdef HAVE_MAC_RAW #define mac_header mac.raw #define network_header nh.raw +#define transport_header h.raw #endif #ifndef HAVE_SKBUFF_HEADER_HELPERS diff --git a/datapath/linux-2.6/compat-2.6/include/net/dst.h b/datapath/linux-2.6/compat-2.6/include/net/dst.h new file mode 100644 index 00000000..edb0f75e --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/net/dst.h @@ -0,0 +1,18 @@ +#ifndef __NET_DST_WRAPPER_H +#define __NET_DST_WRAPPER_H 1 + +#include_next + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + +static inline void skb_dst_drop(struct sk_buff *skb) +{ + if (skb->dst) + dst_release(skb_dst(skb)); + skb->dst = 0UL; +} + +#endif /* linux kernel < 2.6.31 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/net/ipip.h b/datapath/linux-2.6/compat-2.6/include/net/ipip.h new file mode 100644 index 00000000..2eca5f8b --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/net/ipip.h @@ -0,0 +1,93 @@ +#ifndef __NET_IPIP_WRAPPER_H +#define __NET_IPIP_WRAPPER_H 1 + +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) + +#include +#include + +/* Keep error state on tunnel for 30 sec */ +#define IPTUNNEL_ERR_TIMEO (30*HZ) + +struct ip_tunnel +{ + struct ip_tunnel *next; + struct net_device *dev; +#ifndef HAVE_NETDEV_STATS + struct net_device_stats stat; +#endif + + int err_count; /* Number of arrived ICMP errors */ + unsigned long err_time; /* Time when the last ICMP error arrived */ + + /* These four fields used only by GRE */ + __u32 i_seqno; /* The last seen seqno */ + __u32 o_seqno; /* The last output seqno */ + int hlen; /* Precalculated GRE header length */ + int mlink; + + struct ip_tunnel_parm parms; + + struct ip_tunnel_prl_entry *prl; /* potential router list */ + unsigned int prl_count; /* # of entries in PRL */ +}; + +/* ISATAP: default interval between RS in secondy */ +#define IPTUNNEL_RS_DEFAULT_DELAY (900) + +struct ip_tunnel_prl_entry +{ + struct ip_tunnel_prl_entry *next; + __be32 addr; + u16 flags; + unsigned long rs_delay; + struct timer_list rs_timer; + struct ip_tunnel *tunnel; + spinlock_t lock; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) +#define IPTUNNEL_XMIT() do { \ + int err; \ + int pkt_len = skb->len - skb_transport_offset(skb); \ + \ + skb->ip_summed = CHECKSUM_NONE; \ + iph->tot_len = htons(skb->len); \ + ip_select_ident(iph, &rt->u.dst, NULL); \ + ip_send_check(iph); \ + \ + err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\ + if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { \ + stats->tx_bytes += pkt_len; \ + stats->tx_packets++; \ + } else { \ + stats->tx_errors++; \ + stats->tx_aborted_errors++; \ + } \ +} while (0) +#else +#define IPTUNNEL_XMIT() do { \ + int err; \ + int pkt_len = skb->len; \ + \ + skb->ip_summed = CHECKSUM_NONE; \ + ip_select_ident(iph, &rt->u.dst, NULL); \ + \ + err = ip_local_out(skb); \ + if (net_xmit_eval(err) == 0) { \ + stats->tx_bytes += pkt_len; \ + stats->tx_packets++; \ + } else { \ + stats->tx_errors++; \ + stats->tx_aborted_errors++; \ + } \ +} while (0) +#endif + +#else +#include_next +#endif /* kernel < 2.6.32 */ + +#endif /* net/ipip.h wrapper */ diff --git a/datapath/linux-2.6/compat-2.6/include/net/net_namespace.h b/datapath/linux-2.6/compat-2.6/include/net/net_namespace.h new file mode 100644 index 00000000..9b66c91c --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/net/net_namespace.h @@ -0,0 +1,26 @@ +#ifndef __NET_NAMESPACE_WRAPPER_H +#define __NET_NAMESPACE_WRAPPER_H 1 + +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) +#include_next +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +struct net; + +struct pernet_operations { + struct list_head list; + int (*init)(struct net *net); + void (*exit)(struct net *net); +}; +#endif /* linux kernel < 2.6.24 */ + +extern int register_pernet_gen_device(int *id, struct pernet_operations *); +extern void unregister_pernet_gen_device(int id, struct pernet_operations *); + +#endif /* linux kernel < 2.6.26 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/net/netns/generic.h b/datapath/linux-2.6/compat-2.6/include/net/netns/generic.h new file mode 100644 index 00000000..f70bc87e --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/net/netns/generic.h @@ -0,0 +1,16 @@ +#ifndef __NET_NETNS_GENERIC_WRAPPER_H +#define __NET_NETNS_GENERIC_WRAPPER_H 1 + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + +struct net; + +extern void *net_generic(struct net *net, int id); +extern int net_assign_generic(struct net *net, int id, void *data); + +#else +#include_next +#endif /* linux kernel < 2.6.26 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/include/net/route.h b/datapath/linux-2.6/compat-2.6/include/net/route.h new file mode 100644 index 00000000..867f4077 --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/include/net/route.h @@ -0,0 +1,14 @@ +#ifndef __NET_ROUTE_WRAPPER_H +#define __NET_ROUTE_WRAPPER_H 1 + +#include_next + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + +#define ip_route_output_key(net, rp, flp) \ + ip_route_output_key((rp), (flp)) + +#endif /* linux kernel < 2.6.25 */ + +#endif diff --git a/datapath/linux-2.6/compat-2.6/net_namespace-ip_gre.c b/datapath/linux-2.6/compat-2.6/net_namespace-ip_gre.c new file mode 100644 index 00000000..323b6446 --- /dev/null +++ b/datapath/linux-2.6/compat-2.6/net_namespace-ip_gre.c @@ -0,0 +1,49 @@ +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + +#include +#include +#include + +/* This trivial implementation assumes that there is only a single pernet + * generic device registered and that the caller is well behaved. It only + * weakly attempts to check that these conditions are true. */ + +static bool device_registered; +static void *ng_data; + +int register_pernet_gen_device(int *id, struct pernet_operations *ops) +{ + BUG_ON(device_registered); + + *id = 1; + device_registered = true; + + if (ops->init == NULL) + return 0; + return ops->init(NULL); +} + +void unregister_pernet_gen_device(int id, struct pernet_operations *ops) +{ + device_registered = false; + if (ops->exit) + ops->exit(NULL); +} + +int net_assign_generic(struct net *net, int id, void *data) +{ + BUG_ON(id != 1); + + ng_data = data; + return 0; +} + +void *net_generic(struct net *net, int id) +{ + BUG_ON(id != 1); + + return ng_data; +} + +#endif /* kernel < 2.6.26 */