summaryrefslogtreecommitdiff
path: root/include/net
diff options
context:
space:
mode:
Diffstat (limited to 'include/net')
-rw-r--r--include/net/addrconf.h3
-rw-r--r--include/net/af_unix.h3
-rw-r--r--include/net/arp.h28
-rw-r--r--include/net/caif/caif_hsi.h71
-rw-r--r--include/net/dn_route.h2
-rw-r--r--include/net/dst.h77
-rw-r--r--include/net/dst_ops.h10
-rw-r--r--include/net/fib_rules.h1
-rw-r--r--include/net/flow.h4
-rw-r--r--include/net/genetlink.h2
-rw-r--r--include/net/inet6_connection_sock.h3
-rw-r--r--include/net/inet_common.h6
-rw-r--r--include/net/inet_connection_sock.h6
-rw-r--r--include/net/inet_hashtables.h4
-rw-r--r--include/net/inet_sock.h2
-rw-r--r--include/net/inetpeer.h95
-rw-r--r--include/net/ip.h8
-rw-r--r--include/net/ip6_fib.h35
-rw-r--r--include/net/ip6_route.h41
-rw-r--r--include/net/ip6_tunnel.h2
-rw-r--r--include/net/ip_fib.h80
-rw-r--r--include/net/ip_vs.h2
-rw-r--r--include/net/ipv6.h39
-rw-r--r--include/net/mac802154.h8
-rw-r--r--include/net/ndisc.h50
-rw-r--r--include/net/neighbour.h26
-rw-r--r--include/net/net_namespace.h1
-rw-r--r--include/net/netevent.h4
-rw-r--r--include/net/netfilter/nf_conntrack.h35
-rw-r--r--include/net/netfilter/nf_conntrack_core.h4
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h2
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h4
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h9
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h29
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h11
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h33
-rw-r--r--include/net/netfilter/nf_nat_helper.h4
-rw-r--r--include/net/netfilter/nfnetlink_queue.h43
-rw-r--r--include/net/netns/conntrack.h55
-rw-r--r--include/net/netns/ipv4.h14
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--include/net/phonet/gprs.h2
-rw-r--r--include/net/protocol.h8
-rw-r--r--include/net/route.h32
-rw-r--r--include/net/sch_generic.h7
-rw-r--r--include/net/sctp/sctp.h6
-rw-r--r--include/net/sctp/structs.h8
-rw-r--r--include/net/sctp/tsnmap.h3
-rw-r--r--include/net/sock.h7
-rw-r--r--include/net/tcp.h46
-rw-r--r--include/net/timewait_sock.h8
-rw-r--r--include/net/xfrm.h12
52 files changed, 730 insertions, 266 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f2b801c4b555..089a09d001d1 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -46,7 +46,8 @@ struct prefix_info {
#include <net/if_inet6.h>
#include <net/ipv6.h>
-#define IN6_ADDR_HSIZE 16
+#define IN6_ADDR_HSIZE_SHIFT 4
+#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
extern int addrconf_init(void);
extern void addrconf_cleanup(void);
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 2ee33da36a7a..b5f8988e4283 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -14,10 +14,11 @@ extern struct sock *unix_get_socket(struct file *filp);
extern struct sock *unix_peer_get(struct sock *);
#define UNIX_HASH_SIZE 256
+#define UNIX_HASH_BITS 8
extern unsigned int unix_tot_inflight;
extern spinlock_t unix_table_lock;
-extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
+extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
struct unix_address {
atomic_t refcnt;
diff --git a/include/net/arp.h b/include/net/arp.h
index 4a1f3fb562eb..4617d9841132 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -15,24 +15,34 @@ static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd
return val * hash_rnd;
}
-static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
+static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
{
- struct neigh_hash_table *nht;
+ struct neigh_hash_table *nht = rcu_dereference_bh(arp_tbl.nht);
struct neighbour *n;
u32 hash_val;
- rcu_read_lock_bh();
- nht = rcu_dereference_bh(arp_tbl.nht);
+ if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
+ key = 0;
+
hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
n != NULL;
n = rcu_dereference_bh(n->next)) {
- if (n->dev == dev && *(u32 *)n->primary_key == key) {
- if (!atomic_inc_not_zero(&n->refcnt))
- n = NULL;
- break;
- }
+ if (n->dev == dev && *(u32 *)n->primary_key == key)
+ return n;
}
+
+ return NULL;
+}
+
+static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
+{
+ struct neighbour *n;
+
+ rcu_read_lock_bh();
+ n = __ipv4_neigh_lookup_noref(dev, key);
+ if (n && !atomic_inc_not_zero(&n->refcnt))
+ n = NULL;
rcu_read_unlock_bh();
return n;
diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h
index 439dadc8102f..bcb9cc3ce98b 100644
--- a/include/net/caif/caif_hsi.h
+++ b/include/net/caif/caif_hsi.h
@@ -93,25 +93,25 @@ struct cfhsi_desc {
#endif
/* Structure implemented by the CAIF HSI driver. */
-struct cfhsi_drv {
- void (*tx_done_cb) (struct cfhsi_drv *drv);
- void (*rx_done_cb) (struct cfhsi_drv *drv);
- void (*wake_up_cb) (struct cfhsi_drv *drv);
- void (*wake_down_cb) (struct cfhsi_drv *drv);
+struct cfhsi_cb_ops {
+ void (*tx_done_cb) (struct cfhsi_cb_ops *drv);
+ void (*rx_done_cb) (struct cfhsi_cb_ops *drv);
+ void (*wake_up_cb) (struct cfhsi_cb_ops *drv);
+ void (*wake_down_cb) (struct cfhsi_cb_ops *drv);
};
/* Structure implemented by HSI device. */
-struct cfhsi_dev {
- int (*cfhsi_up) (struct cfhsi_dev *dev);
- int (*cfhsi_down) (struct cfhsi_dev *dev);
- int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_dev *dev);
- int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_dev *dev);
- int (*cfhsi_wake_up) (struct cfhsi_dev *dev);
- int (*cfhsi_wake_down) (struct cfhsi_dev *dev);
- int (*cfhsi_get_peer_wake) (struct cfhsi_dev *dev, bool *status);
- int (*cfhsi_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy);
- int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev);
- struct cfhsi_drv *drv;
+struct cfhsi_ops {
+ int (*cfhsi_up) (struct cfhsi_ops *dev);
+ int (*cfhsi_down) (struct cfhsi_ops *dev);
+ int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_ops *dev);
+ int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_ops *dev);
+ int (*cfhsi_wake_up) (struct cfhsi_ops *dev);
+ int (*cfhsi_wake_down) (struct cfhsi_ops *dev);
+ int (*cfhsi_get_peer_wake) (struct cfhsi_ops *dev, bool *status);
+ int (*cfhsi_fifo_occupancy) (struct cfhsi_ops *dev, size_t *occupancy);
+ int (*cfhsi_rx_cancel)(struct cfhsi_ops *dev);
+ struct cfhsi_cb_ops *cb_ops;
};
/* Structure holds status of received CAIF frames processing */
@@ -132,17 +132,26 @@ enum {
CFHSI_PRIO_LAST,
};
+struct cfhsi_config {
+ u32 inactivity_timeout;
+ u32 aggregation_timeout;
+ u32 head_align;
+ u32 tail_align;
+ u32 q_high_mark;
+ u32 q_low_mark;
+};
+
/* Structure implemented by CAIF HSI drivers. */
struct cfhsi {
struct caif_dev_common cfdev;
struct net_device *ndev;
struct platform_device *pdev;
struct sk_buff_head qhead[CFHSI_PRIO_LAST];
- struct cfhsi_drv drv;
- struct cfhsi_dev *dev;
+ struct cfhsi_cb_ops cb_ops;
+ struct cfhsi_ops *ops;
int tx_state;
struct cfhsi_rx_state rx_state;
- unsigned long inactivity_timeout;
+ struct cfhsi_config cfg;
int rx_len;
u8 *rx_ptr;
u8 *tx_buf;
@@ -150,8 +159,6 @@ struct cfhsi {
u8 *rx_flip_buf;
spinlock_t lock;
int flow_off_sent;
- u32 q_low_mark;
- u32 q_high_mark;
struct list_head list;
struct work_struct wake_up_work;
struct work_struct wake_down_work;
@@ -164,13 +171,31 @@ struct cfhsi {
struct timer_list rx_slowpath_timer;
/* TX aggregation */
- unsigned long aggregation_timeout;
int aggregation_len;
struct timer_list aggregation_timer;
unsigned long bits;
};
-
extern struct platform_driver cfhsi_driver;
+/**
+ * enum ifla_caif_hsi - CAIF HSI NetlinkRT parameters.
+ * @IFLA_CAIF_HSI_INACTIVITY_TOUT: Inactivity timeout before
+ * taking the HSI wakeline down, in milliseconds.
+ * When using RT Netlink to create, destroy or configure a CAIF HSI interface,
+ * enum ifla_caif_hsi is used to specify the configuration attributes.
+ */
+enum ifla_caif_hsi {
+ __IFLA_CAIF_HSI_UNSPEC,
+ __IFLA_CAIF_HSI_INACTIVITY_TOUT,
+ __IFLA_CAIF_HSI_AGGREGATION_TOUT,
+ __IFLA_CAIF_HSI_HEAD_ALIGN,
+ __IFLA_CAIF_HSI_TAIL_ALIGN,
+ __IFLA_CAIF_HSI_QHIGH_WATERMARK,
+ __IFLA_CAIF_HSI_QLOW_WATERMARK,
+ __IFLA_CAIF_HSI_MAX
+};
+
+extern struct cfhsi_ops *cfhsi_get_ops(void);
+
#endif /* CAIF_HSI_H_ */
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index c507e05d172f..4f7d6a182381 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -67,6 +67,8 @@ extern void dn_rt_cache_flush(int delay);
struct dn_route {
struct dst_entry dst;
+ struct neighbour *n;
+
struct flowidn fld;
__le16 rt_saddr;
diff --git a/include/net/dst.h b/include/net/dst.h
index 8197eadca819..51610468c63d 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -42,16 +42,16 @@ struct dst_entry {
struct dst_entry *from;
};
struct dst_entry *path;
- struct neighbour __rcu *_neighbour;
+ void *__pad0;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
#else
void *__pad1;
#endif
- int (*input)(struct sk_buff*);
- int (*output)(struct sk_buff*);
+ int (*input)(struct sk_buff *);
+ int (*output)(struct sk_buff *);
- int flags;
+ unsigned short flags;
#define DST_HOST 0x0001
#define DST_NOXFRM 0x0002
#define DST_NOPOLICY 0x0004
@@ -62,6 +62,8 @@ struct dst_entry {
#define DST_FAKE_RTABLE 0x0080
#define DST_XFRM_TUNNEL 0x0100
+ unsigned short pending_confirm;
+
short error;
short obsolete;
unsigned short header_len; /* more space at head required */
@@ -94,21 +96,6 @@ struct dst_entry {
};
};
-static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst)
-{
- return rcu_dereference(dst->_neighbour);
-}
-
-static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst)
-{
- return rcu_dereference_raw(dst->_neighbour);
-}
-
-static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh)
-{
- rcu_assign_pointer(dst->_neighbour, neigh);
-}
-
extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
extern const u32 dst_default_metrics[RTAX_MAX];
@@ -222,12 +209,6 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr
return msecs_to_jiffies(dst_metric(dst, metric));
}
-static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
- unsigned long rtt)
-{
- dst_metric_set(dst, metric, jiffies_to_msecs(rtt));
-}
-
static inline u32
dst_allfrag(const struct dst_entry *dst)
{
@@ -241,7 +222,7 @@ dst_metric_locked(const struct dst_entry *dst, int metric)
return dst_metric(dst, RTAX_LOCK) & (1<<metric);
}
-static inline void dst_hold(struct dst_entry * dst)
+static inline void dst_hold(struct dst_entry *dst)
{
/*
* If your kernel compilation stops here, please check
@@ -264,8 +245,7 @@ static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
dst->lastuse = time;
}
-static inline
-struct dst_entry * dst_clone(struct dst_entry * dst)
+static inline struct dst_entry *dst_clone(struct dst_entry *dst)
{
if (dst)
atomic_inc(&dst->__refcnt);
@@ -371,12 +351,13 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
}
extern int dst_discard(struct sk_buff *skb);
-extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev,
- int initial_ref, int initial_obsolete, int flags);
-extern void __dst_free(struct dst_entry * dst);
-extern struct dst_entry *dst_destroy(struct dst_entry * dst);
+extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
+ int initial_ref, int initial_obsolete,
+ unsigned short flags);
+extern void __dst_free(struct dst_entry *dst);
+extern struct dst_entry *dst_destroy(struct dst_entry *dst);
-static inline void dst_free(struct dst_entry * dst)
+static inline void dst_free(struct dst_entry *dst)
{
if (dst->obsolete > 1)
return;
@@ -396,19 +377,35 @@ static inline void dst_rcu_free(struct rcu_head *head)
static inline void dst_confirm(struct dst_entry *dst)
{
- if (dst) {
- struct neighbour *n;
+ dst->pending_confirm = 1;
+}
+
+static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
+ struct sk_buff *skb)
+{
+ struct hh_cache *hh;
- rcu_read_lock();
- n = dst_get_neighbour_noref(dst);
- neigh_confirm(n);
- rcu_read_unlock();
+ if (unlikely(dst->pending_confirm)) {
+ n->confirmed = jiffies;
+ dst->pending_confirm = 0;
}
+
+ hh = &n->hh;
+ if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
+ return neigh_hh_output(hh, skb);
+ else
+ return n->output(n, skb);
}
static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
- return dst->ops->neigh_lookup(dst, daddr);
+ return dst->ops->neigh_lookup(dst, NULL, daddr);
+}
+
+static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
+ struct sk_buff *skb)
+{
+ return dst->ops->neigh_lookup(dst, skb, NULL);
}
static inline void dst_link_failure(struct sk_buff *skb)
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index 3682a0a076c1..2f26dfb8450e 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -8,6 +8,7 @@ struct dst_entry;
struct kmem_cachep;
struct net_device;
struct sk_buff;
+struct sock;
struct dst_ops {
unsigned short family;
@@ -24,9 +25,14 @@ struct dst_ops {
struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *);
- void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
+ void (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
+ struct sk_buff *skb, u32 mtu);
+ void (*redirect)(struct dst_entry *dst, struct sock *sk,
+ struct sk_buff *skb);
int (*local_out)(struct sk_buff *skb);
- struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
+ struct neighbour * (*neigh_lookup)(const struct dst_entry *dst,
+ struct sk_buff *skb,
+ const void *daddr);
struct kmem_cache *kmem_cachep;
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 075f1e3a0fed..e361f4882426 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -52,6 +52,7 @@ struct fib_rules_ops {
struct sk_buff *,
struct fib_rule_hdr *,
struct nlattr **);
+ void (*delete)(struct fib_rule *);
int (*compare)(struct fib_rule *,
struct fib_rule_hdr *,
struct nlattr **);
diff --git a/include/net/flow.h b/include/net/flow.h
index 6c469dbdb917..ce9cb7656b47 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -20,8 +20,8 @@ struct flowi_common {
__u8 flowic_proto;
__u8 flowic_flags;
#define FLOWI_FLAG_ANYSRC 0x01
-#define FLOWI_FLAG_PRECOW_METRICS 0x02
-#define FLOWI_FLAG_CAN_SLEEP 0x04
+#define FLOWI_FLAG_CAN_SLEEP 0x02
+#define FLOWI_FLAG_RT_NOCACHE 0x04
__u32 flowic_secid;
};
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index ccb68880abf5..48905cd3884c 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -5,6 +5,8 @@
#include <net/netlink.h>
#include <net/net_namespace.h>
+#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
+
/**
* struct genl_multicast_group - generic netlink multicast group
* @name: name of the multicast group, names are per-family
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 1866a676c810..04642c920431 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -26,6 +26,7 @@ extern int inet6_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb, bool relax);
extern struct dst_entry* inet6_csk_route_req(struct sock *sk,
+ struct flowi6 *fl6,
const struct request_sock *req);
extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
@@ -42,4 +43,6 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl);
+
+extern struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index 22fac9892b16..234008782c8c 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -14,9 +14,11 @@ struct sockaddr;
struct socket;
extern int inet_release(struct socket *sock);
-extern int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
+extern int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
-extern int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
+extern int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len, int flags);
+extern int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
extern int inet_accept(struct socket *sock, struct socket *newsock, int flags);
extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock,
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 7d83f90f203f..2cf44b4ed2e6 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -43,7 +43,6 @@ struct inet_connection_sock_af_ops {
struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst);
- struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it);
u16 net_header_len;
u16 net_frag_header_len;
u16 sockaddr_len;
@@ -251,7 +250,8 @@ extern int inet_csk_get_port(struct sock *sk, unsigned short snum);
extern struct dst_entry* inet_csk_route_req(struct sock *sk,
struct flowi4 *fl4,
- const struct request_sock *req);
+ const struct request_sock *req,
+ bool nocache);
extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk,
struct sock *newsk,
const struct request_sock *req);
@@ -337,4 +337,6 @@ extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
+
+extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET_CONNECTION_SOCK_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 808fc5f76b03..54be0287eb98 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -379,10 +379,10 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
const __be16 sport,
const __be16 dport)
{
- struct sock *sk;
+ struct sock *sk = skb_steal_sock(skb);
const struct iphdr *iph = ip_hdr(skb);
- if (unlikely(sk = skb_steal_sock(skb)))
+ if (sk)
return sk;
else
return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index ae17e1352d7e..924d7b98ab60 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -245,8 +245,6 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl)
flags |= FLOWI_FLAG_ANYSRC;
- if (sk->sk_protocol == IPPROTO_TCP)
- flags |= FLOWI_FLAG_PRECOW_METRICS;
return flags;
}
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index b94765e38e80..53f464d7cddc 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -36,22 +36,19 @@ struct inet_peer {
u32 metrics[RTAX_MAX];
u32 rate_tokens; /* rate limiting for ICMP */
unsigned long rate_last;
- unsigned long pmtu_expires;
- u32 pmtu_orig;
- u32 pmtu_learned;
- struct inetpeer_addr_base redirect_learned;
- struct list_head gc_list;
+ union {
+ struct list_head gc_list;
+ struct rcu_head gc_rcu;
+ };
/*
* Once inet_peer is queued for deletion (refcnt == -1), following fields
- * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
+ * are not available: rid, ip_id_count
* We can share memory with rcu_head to help keep inet_peer small.
*/
union {
struct {
atomic_t rid; /* Frag reception counter */
atomic_t ip_id_count; /* IP ID for the next packet */
- __u32 tcp_ts;
- __u32 tcp_ts_stamp;
};
struct rcu_head rcu;
struct inet_peer *gc_next;
@@ -62,6 +59,69 @@ struct inet_peer {
atomic_t refcnt;
};
+struct inet_peer_base {
+ struct inet_peer __rcu *root;
+ seqlock_t lock;
+ u32 flush_seq;
+ int total;
+};
+
+#define INETPEER_BASE_BIT 0x1UL
+
+static inline struct inet_peer *inetpeer_ptr(unsigned long val)
+{
+ BUG_ON(val & INETPEER_BASE_BIT);
+ return (struct inet_peer *) val;
+}
+
+static inline struct inet_peer_base *inetpeer_base_ptr(unsigned long val)
+{
+ if (!(val & INETPEER_BASE_BIT))
+ return NULL;
+ val &= ~INETPEER_BASE_BIT;
+ return (struct inet_peer_base *) val;
+}
+
+static inline bool inetpeer_ptr_is_peer(unsigned long val)
+{
+ return !(val & INETPEER_BASE_BIT);
+}
+
+static inline void __inetpeer_ptr_set_peer(unsigned long *val, struct inet_peer *peer)
+{
+ /* This implicitly clears INETPEER_BASE_BIT */
+ *val = (unsigned long) peer;
+}
+
+static inline bool inetpeer_ptr_set_peer(unsigned long *ptr, struct inet_peer *peer)
+{
+ unsigned long val = (unsigned long) peer;
+ unsigned long orig = *ptr;
+
+ if (!(orig & INETPEER_BASE_BIT) ||
+ cmpxchg(ptr, orig, val) != orig)
+ return false;
+ return true;
+}
+
+static inline void inetpeer_init_ptr(unsigned long *ptr, struct inet_peer_base *base)
+{
+ *ptr = (unsigned long) base | INETPEER_BASE_BIT;
+}
+
+static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from)
+{
+ unsigned long val = *from;
+
+ *to = val;
+ if (inetpeer_ptr_is_peer(val)) {
+ struct inet_peer *peer = inetpeer_ptr(val);
+ atomic_inc(&peer->refcnt);
+ }
+}
+
+extern void inet_peer_base_init(struct inet_peer_base *);
+
void inet_initpeers(void) __init;
#define INETPEER_METRICS_NEW (~(u32) 0)
@@ -72,31 +132,38 @@ static inline bool inet_metrics_new(const struct inet_peer *p)
}
/* can be called with or without local BH being disabled */
-struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create);
+struct inet_peer *inet_getpeer(struct inet_peer_base *base,
+ const struct inetpeer_addr *daddr,
+ int create);
-static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create)
+static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
+ __be32 v4daddr,
+ int create)
{
struct inetpeer_addr daddr;
daddr.addr.a4 = v4daddr;
daddr.family = AF_INET;
- return inet_getpeer(&daddr, create);
+ return inet_getpeer(base, &daddr, create);
}
-static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create)
+static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
+ const struct in6_addr *v6daddr,
+ int create)
{
struct inetpeer_addr daddr;
*(struct in6_addr *)daddr.addr.a6 = *v6daddr;
daddr.family = AF_INET6;
- return inet_getpeer(&daddr, create);
+ return inet_getpeer(base, &daddr, create);
}
/* can be called from BH context or outside */
extern void inet_putpeer(struct inet_peer *p);
extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
-extern void inetpeer_invalidate_tree(int family);
+extern void inetpeer_invalidate_tree(struct inet_peer_base *);
+extern void inetpeer_invalidate_family(int family);
/*
* temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
diff --git a/include/net/ip.h b/include/net/ip.h
index 83e0619f59d0..bd5e444a19ce 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -158,8 +158,9 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
}
-void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
- const struct ip_reply_arg *arg, unsigned int len);
+void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
+ __be32 saddr, const struct ip_reply_arg *arg,
+ unsigned int len);
struct ipv4_config {
int log_martians;
@@ -210,6 +211,9 @@ extern int inet_peer_threshold;
extern int inet_peer_minttl;
extern int inet_peer_maxttl;
+/* From ip_input.c */
+extern int sysctl_ip_early_demux;
+
/* From ip_output.c */
extern int sysctl_ip_dynaddr;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 0ae759a6c76e..0fedbd8d747a 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -86,6 +86,8 @@ struct fib6_table;
struct rt6_info {
struct dst_entry dst;
+ struct neighbour *n;
+
/*
* Tail elements of dst_entry (__refcnt etc.)
* and these elements (rarely used in hot path) are in
@@ -107,7 +109,7 @@ struct rt6_info {
u32 rt6i_peer_genid;
struct inet6_dev *rt6i_idev;
- struct inet_peer *rt6i_peer;
+ unsigned long _rt6i_peer;
#ifdef CONFIG_XFRM
u32 rt6i_flow_cache_genid;
@@ -118,6 +120,36 @@ struct rt6_info {
u8 rt6i_protocol;
};
+static inline struct inet_peer *rt6_peer_ptr(struct rt6_info *rt)
+{
+ return inetpeer_ptr(rt->_rt6i_peer);
+}
+
+static inline bool rt6_has_peer(struct rt6_info *rt)
+{
+ return inetpeer_ptr_is_peer(rt->_rt6i_peer);
+}
+
+static inline void __rt6_set_peer(struct rt6_info *rt, struct inet_peer *peer)
+{
+ __inetpeer_ptr_set_peer(&rt->_rt6i_peer, peer);
+}
+
+static inline bool rt6_set_peer(struct rt6_info *rt, struct inet_peer *peer)
+{
+ return inetpeer_ptr_set_peer(&rt->_rt6i_peer, peer);
+}
+
+static inline void rt6_init_peer(struct rt6_info *rt, struct inet_peer_base *base)
+{
+ inetpeer_init_ptr(&rt->_rt6i_peer, base);
+}
+
+static inline void rt6_transfer_peer(struct rt6_info *rt, struct rt6_info *ort)
+{
+ inetpeer_transfer_peer(&rt->_rt6i_peer, &ort->_rt6i_peer);
+}
+
static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
{
return ((struct rt6_info *)dst)->rt6i_idev;
@@ -207,6 +239,7 @@ struct fib6_table {
u32 tb6_id;
rwlock_t tb6_lock;
struct fib6_node tb6_root;
+ struct inet_peer_base tb6_peers;
};
#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 37c1a1ed82c1..5fa2af00634a 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -53,16 +53,25 @@ static inline unsigned int rt6_flags2srcprefs(int flags)
return (flags >> 3) & 7;
}
-extern void rt6_bind_peer(struct rt6_info *rt,
- int create);
+extern void rt6_bind_peer(struct rt6_info *rt, int create);
+
+static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create)
+{
+ if (rt6_has_peer(rt))
+ return rt6_peer_ptr(rt);
+
+ rt6_bind_peer(rt, create);
+ return (rt6_has_peer(rt) ? rt6_peer_ptr(rt) : NULL);
+}
static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt)
{
- if (rt->rt6i_peer)
- return rt->rt6i_peer;
+ return __rt6_get_peer(rt, 0);
+}
- rt6_bind_peer(rt, 0);
- return rt->rt6i_peer;
+static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt)
+{
+ return __rt6_get_peer(rt, 1);
}
extern void ip6_route_input(struct sk_buff *skb);
@@ -124,17 +133,12 @@ extern int rt6_route_rcv(struct net_device *dev,
u8 *opt, int len,
const struct in6_addr *gwaddr);
-extern void rt6_redirect(const struct in6_addr *dest,
- const struct in6_addr *src,
- const struct in6_addr *saddr,
- struct neighbour *neigh,
- u8 *lladdr,
- int on_link);
-
-extern void rt6_pmtu_discovery(const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct net_device *dev,
- u32 pmtu);
+extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
+ int oif, u32 mark);
+extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
+ __be32 mtu);
+extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
struct netlink_callback;
@@ -154,7 +158,8 @@ extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
* Store a destination cache entry in a socket
*/
static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst,
- struct in6_addr *daddr, struct in6_addr *saddr)
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct rt6_info *rt = (struct rt6_info *) dst;
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index fc73e667b50e..358fb86f57eb 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -9,6 +9,8 @@
#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
/* IPv6 tunnel */
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 78df0866cc38..2daf096dfc60 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -18,7 +18,9 @@
#include <net/flow.h>
#include <linux/seq_file.h>
+#include <linux/rcupdate.h>
#include <net/fib_rules.h>
+#include <net/inetpeer.h>
struct fib_config {
u8 fc_dst_len;
@@ -45,6 +47,22 @@ struct fib_config {
struct fib_info;
+struct fib_nh_exception {
+ struct fib_nh_exception __rcu *fnhe_next;
+ __be32 fnhe_daddr;
+ u32 fnhe_pmtu;
+ __be32 fnhe_gw;
+ unsigned long fnhe_expires;
+ unsigned long fnhe_stamp;
+};
+
+struct fnhe_hash_bucket {
+ struct fib_nh_exception __rcu *chain;
+};
+
+#define FNHE_HASH_SIZE 2048
+#define FNHE_RECLAIM_DEPTH 5
+
struct fib_nh {
struct net_device *nh_dev;
struct hlist_node nh_hash;
@@ -62,6 +80,7 @@ struct fib_nh {
__be32 nh_gw;
__be32 nh_saddr;
int nh_saddr_genid;
+ struct fnhe_hash_bucket *nh_exceptions;
};
/*
@@ -105,12 +124,10 @@ struct fib_result {
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
+ u32 tclassid;
struct fib_info *fi;
struct fib_table *table;
struct list_head *fa_head;
-#ifdef CONFIG_IP_MULTIPLE_TABLES
- struct fib_rule *r;
-#endif
};
struct fib_result_nl {
@@ -157,11 +174,11 @@ extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
FIB_RES_SADDR(net, res))
struct fib_table {
- struct hlist_node tb_hlist;
- u32 tb_id;
- int tb_default;
- int tb_num_default;
- unsigned long tb_data[0];
+ struct hlist_node tb_hlist;
+ u32 tb_id;
+ int tb_default;
+ int tb_num_default;
+ unsigned long tb_data[0];
};
extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
@@ -214,24 +231,55 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
extern int __net_init fib4_rules_init(struct net *net);
extern void __net_exit fib4_rules_exit(struct net *net);
-#ifdef CONFIG_IP_ROUTE_CLASSID
-extern u32 fib_rules_tclass(const struct fib_result *res);
-#endif
-
-extern int fib_lookup(struct net *n, struct flowi4 *flp, struct fib_result *res);
-
extern struct fib_table *fib_new_table(struct net *net, u32 id);
extern struct fib_table *fib_get_table(struct net *net, u32 id);
+extern int __fib_lookup(struct net *net, struct flowi4 *flp,
+ struct fib_result *res);
+
+static inline int fib_lookup(struct net *net, struct flowi4 *flp,
+ struct fib_result *res)
+{
+ if (!net->ipv4.fib_has_custom_rules) {
+ res->tclassid = 0;
+ if (net->ipv4.fib_local &&
+ !fib_table_lookup(net->ipv4.fib_local, flp, res,
+ FIB_LOOKUP_NOREF))
+ return 0;
+ if (net->ipv4.fib_main &&
+ !fib_table_lookup(net->ipv4.fib_main, flp, res,
+ FIB_LOOKUP_NOREF))
+ return 0;
+ if (net->ipv4.fib_default &&
+ !fib_table_lookup(net->ipv4.fib_default, flp, res,
+ FIB_LOOKUP_NOREF))
+ return 0;
+ return -ENETUNREACH;
+ }
+ return __fib_lookup(net, flp, res);
+}
+
#endif /* CONFIG_IP_MULTIPLE_TABLES */
/* Exported by fib_frontend.c */
extern const struct nla_policy rtm_ipv4_policy[];
extern void ip_fib_init(void);
+extern __be32 fib_compute_spec_dst(struct sk_buff *skb);
extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
u8 tos, int oif, struct net_device *dev,
- __be32 *spec_dst, u32 *itag);
+ struct in_device *idev, u32 *itag);
extern void fib_select_default(struct fib_result *res);
+#ifdef CONFIG_IP_ROUTE_CLASSID
+static inline int fib_num_tclassid_users(struct net *net)
+{
+ return net->ipv4.fib_num_tclassid_users;
+}
+#else
+static inline int fib_num_tclassid_users(struct net *net)
+{
+ return 0;
+}
+#endif
/* Exported by fib_semantics.c */
extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
@@ -253,7 +301,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
#endif
*itag = FIB_RES_NH(*res).nh_tclassid<<16;
#ifdef CONFIG_IP_MULTIPLE_TABLES
- rtag = fib_rules_tclass(res);
+ rtag = res->tclassid;
if (*itag == 0)
*itag = (rtag<<16);
*itag |= (rtag>>16);
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index d6146b4811c2..95374d1696a1 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1425,7 +1425,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (!ct || !nf_ct_is_untracked(ct)) {
- nf_reset(skb);
+ nf_conntrack_put(skb->nfct);
skb->nfct = &nf_ct_untracked_get()->ct_general;
skb->nfctinfo = IP_CT_NEW;
nf_conntrack_get(skb->nfct);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index aecf88436abf..01c34b363a34 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -251,6 +251,8 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
atomic_dec(&fl->users);
}
+extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
+
extern int ip6_ra_control(struct sock *sk, int sel);
extern int ipv6_parse_hopopts(struct sk_buff *skb);
@@ -298,14 +300,23 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr
return memcmp(a1, a2, sizeof(struct in6_addr));
}
-static inline int
+static inline bool
ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
const struct in6_addr *a2)
{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ const unsigned long *ul1 = (const unsigned long *)a1;
+ const unsigned long *ulm = (const unsigned long *)m;
+ const unsigned long *ul2 = (const unsigned long *)a2;
+
+ return !!(((ul1[0] ^ ul2[0]) & ulm[0]) |
+ ((ul1[1] ^ ul2[1]) & ulm[1]));
+#else
return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]));
+#endif
}
static inline void ipv6_addr_prefix(struct in6_addr *pfx,
@@ -335,10 +346,17 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
static inline bool ipv6_addr_equal(const struct in6_addr *a1,
const struct in6_addr *a2)
{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ const unsigned long *ul1 = (const unsigned long *)a1;
+ const unsigned long *ul2 = (const unsigned long *)a2;
+
+ return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL;
+#else
return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
(a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
(a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
(a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
+#endif
}
static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
@@ -391,8 +409,27 @@ bool ip6_frag_match(struct inet_frag_queue *q, void *a);
static inline bool ipv6_addr_any(const struct in6_addr *a)
{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ const unsigned long *ul = (const unsigned long *)a;
+
+ return (ul[0] | ul[1]) == 0UL;
+#else
return (a->s6_addr32[0] | a->s6_addr32[1] |
a->s6_addr32[2] | a->s6_addr32[3]) == 0;
+#endif
+}
+
+static inline u32 ipv6_addr_hash(const struct in6_addr *a)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ const unsigned long *ul = (const unsigned long *)a;
+ unsigned long x = ul[0] ^ ul[1];
+
+ return (u32)(x ^ (x >> 32));
+#else
+ return (__force u32)(a->s6_addr32[0] ^ a->s6_addr32[1] ^
+ a->s6_addr32[2] ^ a->s6_addr32[3]);
+#endif
}
static inline bool ipv6_addr_loopback(const struct in6_addr *a)
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index c9f8ab5cc687..d0d11df9cba1 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -21,6 +21,14 @@
#include <net/af_ieee802154.h>
+/* General MAC frame format:
+ * 2 bytes: Frame Control
+ * 1 byte: Sequence Number
+ * 20 bytes: Addressing fields
+ * 14 bytes: Auxiliary Security Header
+ */
+#define MAC802154_FRAME_HARD_HEADER_LEN (2 + 1 + 20 + 14)
+
/* The following flags are used to indicate changed address settings from
* the stack to the hardware.
*/
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index c02b6ad3f6c5..96a3b5c03e37 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -47,6 +47,8 @@ enum {
#include <linux/icmpv6.h>
#include <linux/in6.h>
#include <linux/types.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
#include <net/neighbour.h>
@@ -80,6 +82,54 @@ struct nd_opt_hdr {
__u8 nd_opt_len;
} __packed;
+/* ND options */
+struct ndisc_options {
+ struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
+#ifdef CONFIG_IPV6_ROUTE_INFO
+ struct nd_opt_hdr *nd_opts_ri;
+ struct nd_opt_hdr *nd_opts_ri_end;
+#endif
+ struct nd_opt_hdr *nd_useropts;
+ struct nd_opt_hdr *nd_useropts_end;
+};
+
+#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
+#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
+#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
+#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
+#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
+#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
+
+#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
+
+extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+ struct ndisc_options *ndopts);
+
+/*
+ * Return the padding between the option length and the start of the
+ * link addr. Currently only IP-over-InfiniBand needs this, although
+ * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
+ * also need a pad of 2.
+ */
+static int ndisc_addr_option_pad(unsigned short type)
+{
+ switch (type) {
+ case ARPHRD_INFINIBAND: return 2;
+ default: return 0;
+ }
+}
+
+static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
+ struct net_device *dev)
+{
+ u8 *lladdr = (u8 *)(p + 1);
+ int lladdrlen = p->nd_opt_len << 3;
+ int prepad = ndisc_addr_option_pad(dev->type);
+ if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
+ return NULL;
+ return lladdr + prepad;
+}
+
static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
{
const u32 *p32 = pkey;
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 6cdfeedb650b..344d8988842a 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -202,9 +202,16 @@ extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl,
struct net *net,
const void *pkey);
-extern struct neighbour * neigh_create(struct neigh_table *tbl,
+extern struct neighbour * __neigh_create(struct neigh_table *tbl,
+ const void *pkey,
+ struct net_device *dev,
+ bool want_ref);
+static inline struct neighbour *neigh_create(struct neigh_table *tbl,
const void *pkey,
- struct net_device *dev);
+ struct net_device *dev)
+{
+ return __neigh_create(tbl, pkey, dev, true);
+}
extern void neigh_destroy(struct neighbour *neigh);
extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
@@ -302,12 +309,6 @@ static inline struct neighbour * neigh_clone(struct neighbour *neigh)
#define neigh_hold(n) atomic_inc(&(n)->refcnt)
-static inline void neigh_confirm(struct neighbour *neigh)
-{
- if (neigh)
- neigh->confirmed = jiffies;
-}
-
static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
{
unsigned long now = jiffies;
@@ -351,15 +352,6 @@ static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
return dev_queue_xmit(skb);
}
-static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
-{
- struct hh_cache *hh = &n->hh;
- if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
- return neigh_hh_output(hh, skb);
- else
- return n->output(n, skb);
-}
-
static inline struct neighbour *
__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat)
{
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ac9195e6a062..ae1cd6c9ba52 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -101,6 +101,7 @@ struct net {
struct netns_xfrm xfrm;
#endif
struct netns_ipvs *ipvs;
+ struct sock *diag_nlsk;
};
diff --git a/include/net/netevent.h b/include/net/netevent.h
index 086f8a5b59dc..3ce4988c9c08 100644
--- a/include/net/netevent.h
+++ b/include/net/netevent.h
@@ -12,10 +12,14 @@
*/
struct dst_entry;
+struct neighbour;
struct netevent_redirect {
struct dst_entry *old;
+ struct neighbour *old_neigh;
struct dst_entry *new;
+ struct neighbour *new_neigh;
+ const void *daddr;
};
enum netevent_notif_type {
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index cce7f6a798bf..f1494feba79f 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -39,36 +39,6 @@ union nf_conntrack_expect_proto {
/* insert expect proto private data here */
};
-/* Add protocol helper include file here */
-#include <linux/netfilter/nf_conntrack_ftp.h>
-#include <linux/netfilter/nf_conntrack_pptp.h>
-#include <linux/netfilter/nf_conntrack_h323.h>
-#include <linux/netfilter/nf_conntrack_sane.h>
-#include <linux/netfilter/nf_conntrack_sip.h>
-
-/* per conntrack: application helper private data */
-union nf_conntrack_help {
- /* insert conntrack helper private data (master) here */
-#if defined(CONFIG_NF_CONNTRACK_FTP) || defined(CONFIG_NF_CONNTRACK_FTP_MODULE)
- struct nf_ct_ftp_master ct_ftp_info;
-#endif
-#if defined(CONFIG_NF_CONNTRACK_PPTP) || \
- defined(CONFIG_NF_CONNTRACK_PPTP_MODULE)
- struct nf_ct_pptp_master ct_pptp_info;
-#endif
-#if defined(CONFIG_NF_CONNTRACK_H323) || \
- defined(CONFIG_NF_CONNTRACK_H323_MODULE)
- struct nf_ct_h323_master ct_h323_info;
-#endif
-#if defined(CONFIG_NF_CONNTRACK_SANE) || \
- defined(CONFIG_NF_CONNTRACK_SANE_MODULE)
- struct nf_ct_sane_master ct_sane_info;
-#endif
-#if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
- struct nf_ct_sip_master ct_sip_info;
-#endif
-};
-
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/timer.h>
@@ -89,12 +59,13 @@ struct nf_conn_help {
/* Helper. if any */
struct nf_conntrack_helper __rcu *helper;
- union nf_conntrack_help help;
-
struct hlist_head expectations;
/* Current number of expected connections */
u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
+
+ /* private helper information. */
+ char data[];
};
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index aced085132e7..d8f5b9f52169 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -28,8 +28,8 @@ extern unsigned int nf_conntrack_in(struct net *net,
extern int nf_conntrack_init(struct net *net);
extern void nf_conntrack_cleanup(struct net *net);
-extern int nf_conntrack_proto_init(void);
-extern void nf_conntrack_proto_fini(void);
+extern int nf_conntrack_proto_init(struct net *net);
+extern void nf_conntrack_proto_fini(struct net *net);
extern bool
nf_ct_get_tuple(const struct sk_buff *skb,
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index a88fb6939387..e1ce1048fe5f 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -78,7 +78,7 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *e;
- if (net->ct.nf_conntrack_event_cb == NULL)
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
return;
e = nf_ct_ecache_find(ct);
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 4619caadd9d1..983f00263243 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -59,10 +59,12 @@ static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
return nf_ct_net(exp->master);
}
+#define NF_CT_EXP_POLICY_NAME_LEN 16
+
struct nf_conntrack_expect_policy {
unsigned int max_expected;
unsigned int timeout;
- const char *name;
+ char name[NF_CT_EXP_POLICY_NAME_LEN];
};
#define NF_CT_EXPECT_CLASS_DEFAULT 0
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index 96755c3798a5..8b4d1fc29096 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -80,10 +80,13 @@ static inline void nf_ct_ext_free(struct nf_conn *ct)
}
/* Add this type, returns pointer to data or NULL. */
-void *
-__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
+void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id,
+ size_t var_alloc_len, gfp_t gfp);
+
#define nf_ct_ext_add(ct, id, gfp) \
- ((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp)))
+ ((id##_TYPE *)__nf_ct_ext_add_length((ct), (id), 0, (gfp)))
+#define nf_ct_ext_add_length(ct, id, len, gfp) \
+ ((id##_TYPE *)__nf_ct_ext_add_length((ct), (id), (len), (gfp)))
#define NF_CT_EXT_F_PREALLOC 0x0001
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 1d1889409b9e..9aad956d1008 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -11,18 +11,27 @@
#define _NF_CONNTRACK_HELPER_H
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_expect.h>
struct module;
+enum nf_ct_helper_flags {
+ NF_CT_HELPER_F_USERSPACE = (1 << 0),
+ NF_CT_HELPER_F_CONFIGURED = (1 << 1),
+};
+
#define NF_CT_HELPER_NAME_LEN 16
struct nf_conntrack_helper {
struct hlist_node hnode; /* Internal use. */
- const char *name; /* name of the module */
+ char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
struct module *me; /* pointer to self */
const struct nf_conntrack_expect_policy *expect_policy;
+ /* length of internal data, ie. sizeof(struct nf_ct_*_master) */
+ size_t data_len;
+
/* Tuple of things we will help (compared against server response) */
struct nf_conntrack_tuple tuple;
@@ -35,8 +44,12 @@ struct nf_conntrack_helper {
void (*destroy)(struct nf_conn *ct);
+ int (*from_nlattr)(struct nlattr *attr, struct nf_conn *ct);
int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
unsigned int expect_class_max;
+
+ unsigned int flags;
+ unsigned int queue_num; /* For user-space helpers. */
};
extern struct nf_conntrack_helper *
@@ -48,7 +61,7 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
-extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
+extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, struct nf_conntrack_helper *helper, gfp_t gfp);
extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
gfp_t flags);
@@ -60,6 +73,15 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
}
+static inline void *nfct_help_data(const struct nf_conn *ct)
+{
+ struct nf_conn_help *help;
+
+ help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+
+ return (void *)help->data;
+}
+
extern int nf_conntrack_helper_init(struct net *net);
extern void nf_conntrack_helper_fini(struct net *net);
@@ -82,4 +104,7 @@ nf_ct_helper_expectfn_find_by_name(const char *name);
struct nf_ct_helper_expectfn *
nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
+extern struct hlist_head *nf_ct_helper_hash;
+extern unsigned int nf_ct_helper_hsize;
+
#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 9699c028b74b..6f7c13f4ac03 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -64,11 +64,12 @@ struct nf_conntrack_l3proto {
size_t nla_size;
#ifdef CONFIG_SYSCTL
- struct ctl_table_header *ctl_table_header;
const char *ctl_table_path;
- struct ctl_table *ctl_table;
#endif /* CONFIG_SYSCTL */
+ /* Init l3proto pernet data */
+ int (*init_net)(struct net *net);
+
/* Module (if any) which this is connected to. */
struct module *me;
};
@@ -76,8 +77,10 @@ struct nf_conntrack_l3proto {
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
/* Protocol registration. */
-extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
-extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+extern int nf_conntrack_l3proto_register(struct net *net,
+ struct nf_conntrack_l3proto *proto);
+extern void nf_conntrack_l3proto_unregister(struct net *net,
+ struct nf_conntrack_l3proto *proto);
extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 3b572bb20aa2..c3be4aef6bf7 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -12,6 +12,7 @@
#include <linux/netlink.h>
#include <net/netlink.h>
#include <net/netfilter/nf_conntrack.h>
+#include <net/netns/generic.h>
struct seq_file;
@@ -86,23 +87,21 @@ struct nf_conntrack_l4proto {
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
struct {
size_t obj_size;
- int (*nlattr_to_obj)(struct nlattr *tb[], void *data);
+ int (*nlattr_to_obj)(struct nlattr *tb[],
+ struct net *net, void *data);
int (*obj_to_nlattr)(struct sk_buff *skb, const void *data);
unsigned int nlattr_max;
const struct nla_policy *nla_policy;
} ctnl_timeout;
#endif
+ int *net_id;
+ /* Init l4proto pernet data */
+ int (*init_net)(struct net *net, u_int16_t proto);
+
+ /* Return the per-net protocol part. */
+ struct nf_proto_net *(*get_net_proto)(struct net *net);
-#ifdef CONFIG_SYSCTL
- struct ctl_table_header **ctl_table_header;
- struct ctl_table *ctl_table;
- unsigned int *ctl_table_users;
-#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
- struct ctl_table_header *ctl_compat_table_header;
- struct ctl_table *ctl_compat_table;
-#endif
-#endif
/* Protocol name */
const char *name;
@@ -123,8 +122,18 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
/* Protocol registration. */
-extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
-extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+extern int nf_conntrack_l4proto_register(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+extern void nf_conntrack_l4proto_unregister(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+
+static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn)
+{
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ kfree(pn->ctl_compat_table);
+ pn->ctl_compat_table = NULL;
+#endif
+}
/* Generic netlink helpers */
extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
index 02bb6c29dc3d..7d8fb7b46c44 100644
--- a/include/net/netfilter/nf_nat_helper.h
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -54,4 +54,8 @@ extern void nf_nat_follow_master(struct nf_conn *ct,
extern s16 nf_nat_get_offset(const struct nf_conn *ct,
enum ip_conntrack_dir dir,
u32 seq);
+
+extern void nf_nat_tcp_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ u32 dir, int off);
+
#endif
diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h
new file mode 100644
index 000000000000..86267a529514
--- /dev/null
+++ b/include/net/netfilter/nfnetlink_queue.h
@@ -0,0 +1,43 @@
+#ifndef _NET_NFNL_QUEUE_H_
+#define _NET_NFNL_QUEUE_H_
+
+#include <linux/netfilter/nf_conntrack_common.h>
+
+struct nf_conn;
+
+#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
+struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
+ enum ip_conntrack_info *ctinfo);
+struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
+ const struct nlattr *attr,
+ enum ip_conntrack_info *ctinfo);
+int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
+void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, int diff);
+#else
+inline struct nf_conn *
+nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
+{
+ return NULL;
+}
+
+inline struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb,
+ const struct nlattr *attr,
+ enum ip_conntrack_info *ctinfo)
+{
+ return NULL;
+}
+
+inline int
+nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+ return 0;
+}
+
+inline void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, int diff)
+{
+}
+#endif /* NF_CONNTRACK */
+#endif
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index a053a19870cf..3aecdc7a84fb 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -4,10 +4,64 @@
#include <linux/list.h>
#include <linux/list_nulls.h>
#include <linux/atomic.h>
+#include <linux/netfilter/nf_conntrack_tcp.h>
struct ctl_table_header;
struct nf_conntrack_ecache;
+struct nf_proto_net {
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *ctl_table_header;
+ struct ctl_table *ctl_table;
+#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
+ struct ctl_table_header *ctl_compat_header;
+ struct ctl_table *ctl_compat_table;
+#endif
+#endif
+ unsigned int users;
+};
+
+struct nf_generic_net {
+ struct nf_proto_net pn;
+ unsigned int timeout;
+};
+
+struct nf_tcp_net {
+ struct nf_proto_net pn;
+ unsigned int timeouts[TCP_CONNTRACK_TIMEOUT_MAX];
+ unsigned int tcp_loose;
+ unsigned int tcp_be_liberal;
+ unsigned int tcp_max_retrans;
+};
+
+enum udp_conntrack {
+ UDP_CT_UNREPLIED,
+ UDP_CT_REPLIED,
+ UDP_CT_MAX
+};
+
+struct nf_udp_net {
+ struct nf_proto_net pn;
+ unsigned int timeouts[UDP_CT_MAX];
+};
+
+struct nf_icmp_net {
+ struct nf_proto_net pn;
+ unsigned int timeout;
+};
+
+struct nf_ip_net {
+ struct nf_generic_net generic;
+ struct nf_tcp_net tcp;
+ struct nf_udp_net udp;
+ struct nf_icmp_net icmp;
+ struct nf_icmp_net icmpv6;
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
+ struct ctl_table_header *ctl_table_header;
+ struct ctl_table *ctl_table;
+#endif
+};
+
struct netns_ct {
atomic_t count;
unsigned int expect_count;
@@ -28,6 +82,7 @@ struct netns_ct {
unsigned int sysctl_log_invalid; /* Log invalid packets */
int sysctl_auto_assign_helper;
bool auto_assign_helper_warned;
+ struct nf_ip_net nf_ct_proto;
#ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_header;
struct ctl_table_header *acct_sysctl_header;
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index bbd023a1c9b9..d909c7fc3da1 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -7,10 +7,12 @@
#include <net/inet_frag.h>
+struct tcpm_hash_bucket;
struct ctl_table_header;
struct ipv4_devconf;
struct fib_rules_ops;
struct hlist_head;
+struct fib_table;
struct sock;
struct netns_ipv4 {
@@ -24,13 +26,21 @@ struct netns_ipv4 {
struct ipv4_devconf *devconf_dflt;
#ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_rules_ops *rules_ops;
+ bool fib_has_custom_rules;
+ struct fib_table *fib_local;
+ struct fib_table *fib_main;
+ struct fib_table *fib_default;
+#endif
+#ifdef CONFIG_IP_ROUTE_CLASSID
+ int fib_num_tclassid_users;
#endif
struct hlist_head *fib_table_hash;
struct sock *fibnl;
struct sock **icmp_sk;
- struct sock *tcp_sock;
-
+ struct inet_peer_base *peers;
+ struct tcpm_hash_bucket *tcp_metrics_hash;
+ unsigned int tcp_metrics_hash_mask;
struct netns_frags frags;
#ifdef CONFIG_NETFILTER
struct xt_table *iptable_filter;
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index b42be53587ba..df0a5456a3fd 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -33,6 +33,7 @@ struct netns_ipv6 {
struct netns_sysctl_ipv6 sysctl;
struct ipv6_devconf *devconf_all;
struct ipv6_devconf *devconf_dflt;
+ struct inet_peer_base *peers;
struct netns_frags frags;
#ifdef CONFIG_NETFILTER
struct xt_table *ip6table_filter;
diff --git a/include/net/phonet/gprs.h b/include/net/phonet/gprs.h
index 928daf595beb..bcd525e39a0b 100644
--- a/include/net/phonet/gprs.h
+++ b/include/net/phonet/gprs.h
@@ -5,7 +5,7 @@
*
* Copyright (C) 2008 Nokia Corporation.
*
- * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
+ * Author: Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 875f4895b033..057f2d315567 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -29,11 +29,15 @@
#include <linux/ipv6.h>
#endif
-#define MAX_INET_PROTOS 256 /* Must be a power of 2 */
-
+/* This is one larger than the largest protocol value that can be
+ * found in an ipv4 or ipv6 header. Since in both cases the protocol
+ * value is presented in a __u8, this is defined to be 256.
+ */
+#define MAX_INET_PROTOS 256
/* This is used to register protocols. */
struct net_protocol {
+ void (*early_demux)(struct sk_buff *skb);
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
int (*gso_send_check)(struct sk_buff *skb);
diff --git a/include/net/route.h b/include/net/route.h
index ed2b78e2375d..ace3cb442519 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -40,7 +40,6 @@
#define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE))
struct fib_nh;
-struct inet_peer;
struct fib_info;
struct rtable {
struct dst_entry dst;
@@ -65,9 +64,7 @@ struct rtable {
__be32 rt_gateway;
/* Miscellaneous cached information */
- __be32 rt_spec_dst; /* RFC1122 specific destination */
- u32 rt_peer_genid;
- struct inet_peer *peer; /* long-living peer info */
+ u32 rt_pmtu;
struct fib_info *fi; /* for client ref to shared metrics */
};
@@ -111,8 +108,6 @@ extern struct ip_rt_acct __percpu *ip_rt_acct;
struct in_device;
extern int ip_rt_init(void);
-extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
- __be32 src, struct net_device *dev);
extern void rt_cache_flush(struct net *net, int how);
extern void rt_cache_flush_batch(struct net *net);
extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
@@ -130,9 +125,9 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr,
{
struct flowi4 fl4 = {
.flowi4_oif = oif,
+ .flowi4_tos = tos,
.daddr = daddr,
.saddr = saddr,
- .flowi4_tos = tos,
};
return ip_route_output_key(net, &fl4);
}
@@ -181,9 +176,13 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s
return ip_route_input_common(skb, dst, src, tos, devin, true);
}
-extern unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph,
- unsigned short new_mtu, struct net_device *dev);
-extern void ip_rt_send_redirect(struct sk_buff *skb);
+extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
+ int oif, u32 mark, u8 protocol, int flow_flags);
+extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu);
+extern void ipv4_redirect(struct sk_buff *skb, struct net *net,
+ int oif, u32 mark, u8 protocol, int flow_flags);
+extern void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk);
+extern void ip_rt_send_redirect(struct sk_buff *skb);
extern unsigned int inet_addr_type(struct net *net, __be32 addr);
extern unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr);
@@ -244,8 +243,6 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
if (inet_sk(sk)->transparent)
flow_flags |= FLOWI_FLAG_ANYSRC;
- if (protocol == IPPROTO_TCP)
- flow_flags |= FLOWI_FLAG_PRECOW_METRICS;
if (can_sleep)
flow_flags |= FLOWI_FLAG_CAN_SLEEP;
@@ -294,17 +291,6 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable
return rt;
}
-extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create);
-
-static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr)
-{
- if (rt->peer)
- return rt->peer;
-
- rt_bind_peer(rt, daddr, 0);
- return rt->peer;
-}
-
static inline int inet_iif(const struct sk_buff *skb)
{
return skb_rtable(skb)->rt_iif;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 55ce96b53b09..9d7d54a00e63 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -220,13 +220,16 @@ struct tcf_proto {
struct qdisc_skb_cb {
unsigned int pkt_len;
- unsigned char data[24];
+ u16 bond_queue_mapping;
+ u16 _pad;
+ unsigned char data[20];
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
{
struct qdisc_skb_cb *qcb;
- BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz);
+
+ BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz);
BUILD_BUG_ON(sizeof(qcb->data) < sz);
}
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index a2ef81466b00..ff499640528b 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -162,6 +162,8 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *,
void sctp_err_finish(struct sock *, struct sctp_association *);
void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu);
+void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
+ struct sk_buff *);
void sctp_icmp_proto_unreachable(struct sock *sk,
struct sctp_association *asoc,
struct sctp_transport *t);
@@ -517,10 +519,10 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
return frag;
}
-static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
+static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_association *asoc)
{
- sctp_assoc_sync_pmtu(asoc);
+ sctp_assoc_sync_pmtu(sk, asoc);
asoc->pmtu_pending = 0;
}
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index e4652fe58958..536e439ddf1d 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -912,6 +912,9 @@ struct sctp_transport {
/* Is this structure kfree()able? */
malloced:1;
+ /* Has this transport moved the ctsn since we last sacked */
+ __u32 sack_generation;
+
struct flowi fl;
/* This is the peer's IP address and port. */
@@ -1088,7 +1091,7 @@ void sctp_transport_burst_limited(struct sctp_transport *);
void sctp_transport_burst_reset(struct sctp_transport *);
unsigned long sctp_transport_timeout(struct sctp_transport *);
void sctp_transport_reset(struct sctp_transport *);
-void sctp_transport_update_pmtu(struct sctp_transport *, u32);
+void sctp_transport_update_pmtu(struct sock *, struct sctp_transport *, u32);
void sctp_transport_immediate_rtx(struct sctp_transport *);
@@ -1584,6 +1587,7 @@ struct sctp_association {
*/
__u8 sack_needed; /* Do we need to sack the peer? */
__u32 sack_cnt;
+ __u32 sack_generation;
/* These are capabilities which our peer advertised. */
__u8 ecn_capable:1, /* Can peer do ECN? */
@@ -1999,7 +2003,7 @@ void sctp_assoc_update(struct sctp_association *old,
__u32 sctp_association_get_next_tsn(struct sctp_association *);
-void sctp_assoc_sync_pmtu(struct sctp_association *);
+void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *);
void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
void sctp_assoc_set_primary(struct sctp_association *,
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index e7728bc14ccf..2c5d2b4d5d1e 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map);
int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
/* Mark this TSN as seen. */
-int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
+int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn,
+ struct sctp_transport *trans);
/* Mark this TSN and all lower as seen. */
void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn);
diff --git a/include/net/sock.h b/include/net/sock.h
index 4a4521699563..88de092df50f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -198,6 +198,7 @@ struct cg_proto;
* @sk_lock: synchronizer
* @sk_rcvbuf: size of receive buffer in bytes
* @sk_wq: sock wait queue and async head
+ * @sk_rx_dst: receive input route used by early tcp demux
* @sk_dst_cache: destination cache
* @sk_dst_lock: destination cache lock
* @sk_policy: flow policy
@@ -317,6 +318,7 @@ struct sock {
struct xfrm_policy *sk_policy[2];
#endif
unsigned long sk_flags;
+ struct dst_entry *sk_rx_dst;
struct dst_entry *sk_dst_cache;
spinlock_t sk_dst_lock;
atomic_t sk_wmem_alloc;
@@ -856,6 +858,8 @@ struct proto {
int (*backlog_rcv) (struct sock *sk,
struct sk_buff *skb);
+ void (*release_cb)(struct sock *sk);
+
/* Keeping track of sk's, looking them up, and port selection methods. */
void (*hash)(struct sock *sk);
void (*unhash)(struct sock *sk);
@@ -1426,6 +1430,7 @@ extern struct sk_buff *sock_rmalloc(struct sock *sk,
gfp_t priority);
extern void sock_wfree(struct sk_buff *skb);
extern void sock_rfree(struct sk_buff *skb);
+extern void sock_edemux(struct sk_buff *skb);
extern int sock_setsockopt(struct socket *sock, int level,
int op, char __user *optval,
@@ -2152,7 +2157,7 @@ static inline void sk_change_net(struct sock *sk, struct net *net)
static inline struct sock *skb_steal_sock(struct sk_buff *skb)
{
- if (unlikely(skb->sk)) {
+ if (skb->sk) {
struct sock *sk = skb->sk;
skb->destructor = NULL;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e79aa48d9fc1..bc7c134ec054 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -170,6 +170,11 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */
#define TCPOPT_COOKIE 253 /* Cookie extension (experimental) */
+#define TCPOPT_EXP 254 /* Experimental */
+/* Magic number to be after the option value for sharing TCP
+ * experimental options. See draft-ietf-tcpm-experimental-options-00.txt
+ */
+#define TCPOPT_FASTOPEN_MAGIC 0xF989
/*
* TCP option lengths
@@ -180,6 +185,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_SACK_PERM 2
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_MD5SIG 18
+#define TCPOLEN_EXP_FASTOPEN_BASE 4
#define TCPOLEN_COOKIE_BASE 2 /* Cookie-less header extension */
#define TCPOLEN_COOKIE_PAIR 3 /* Cookie pair header extension */
#define TCPOLEN_COOKIE_MIN (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN)
@@ -206,6 +212,10 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
/* TCP initial congestion window as per draft-hkchu-tcpm-initcwnd-01 */
#define TCP_INIT_CWND 10
+/* Bit Flags for sysctl_tcp_fastopen */
+#define TFO_CLIENT_ENABLE 1
+#define TFO_CLIENT_NO_COOKIE 4 /* Data in SYN w/o cookie option */
+
extern struct inet_timewait_death_row tcp_death_row;
/* sysctl variables for tcp */
@@ -222,6 +232,7 @@ extern int sysctl_tcp_retries1;
extern int sysctl_tcp_retries2;
extern int sysctl_tcp_orphan_retries;
extern int sysctl_tcp_syncookies;
+extern int sysctl_tcp_fastopen;
extern int sysctl_tcp_retrans_collapse;
extern int sysctl_tcp_stdurg;
extern int sysctl_tcp_rfc1337;
@@ -253,6 +264,8 @@ extern int sysctl_tcp_cookie_size;
extern int sysctl_tcp_thin_linear_timeouts;
extern int sysctl_tcp_thin_dupack;
extern int sysctl_tcp_early_retrans;
+extern int sysctl_tcp_limit_output_bytes;
+extern int sysctl_tcp_challenge_ack_limit;
extern atomic_long_t tcp_memory_allocated;
extern struct percpu_counter tcp_sockets_allocated;
@@ -321,19 +334,22 @@ extern struct proto tcp_prot;
extern void tcp_init_mem(struct net *net);
+extern void tcp_tasklet_init(void);
+
extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how);
+extern void tcp_v4_early_demux(struct sk_buff *skb);
extern int tcp_v4_rcv(struct sk_buff *skb);
-extern struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it);
-extern void *tcp_v4_tw_get_peer(struct sock *sk);
+extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t size);
extern int tcp_sendpage(struct sock *sk, struct page *page, int offset,
size_t size, int flags);
+extern void tcp_release_cb(struct sock *sk);
extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, unsigned int len);
@@ -388,6 +404,19 @@ extern void tcp_enter_frto(struct sock *sk);
extern void tcp_enter_loss(struct sock *sk, int how);
extern void tcp_clear_retrans(struct tcp_sock *tp);
extern void tcp_update_metrics(struct sock *sk);
+extern void tcp_init_metrics(struct sock *sk);
+extern void tcp_metrics_init(void);
+extern bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check);
+extern bool tcp_remember_stamp(struct sock *sk);
+extern bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw);
+extern void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
+ struct tcp_fastopen_cookie *cookie,
+ int *syn_loss, unsigned long *last_syn_loss);
+extern void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
+ struct tcp_fastopen_cookie *cookie,
+ bool syn_lost);
+extern void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst);
+extern void tcp_disable_fack(struct tcp_sock *tp);
extern void tcp_close(struct sock *sk, long timeout);
extern void tcp_init_sock(struct sock *sk);
extern unsigned int tcp_poll(struct file * file, struct socket *sock,
@@ -406,7 +435,7 @@ extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t len, int nonblock, int flags, int *addr_len);
extern void tcp_parse_options(const struct sk_buff *skb,
struct tcp_options_received *opt_rx, const u8 **hvpp,
- int estab);
+ int estab, struct tcp_fastopen_cookie *foc);
extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
/*
@@ -556,6 +585,8 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
return (tp->srtt >> 3) + tp->rttvar;
}
+extern void tcp_set_rto(struct sock *sk);
+
static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
{
tp->pred_flags = htonl((tp->tcp_header_len << 26) |
@@ -1264,6 +1295,15 @@ extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff
extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
const struct tcp_md5sig_key *key);
+struct tcp_fastopen_request {
+ /* Fast Open cookie. Size 0 means a cookie request */
+ struct tcp_fastopen_cookie cookie;
+ struct msghdr *data; /* data in MSG_FASTOPEN */
+ u16 copied; /* queued in tcp_connect() */
+};
+
+void tcp_free_fastopen_req(struct tcp_sock *tp);
+
/* write queue abstraction */
static inline void tcp_write_queue_purge(struct sock *sk)
{
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
index 8d6689cb2c66..68f0ecad6c6e 100644
--- a/include/net/timewait_sock.h
+++ b/include/net/timewait_sock.h
@@ -22,7 +22,6 @@ struct timewait_sock_ops {
int (*twsk_unique)(struct sock *sk,
struct sock *sktw, void *twp);
void (*twsk_destructor)(struct sock *sk);
- void *(*twsk_getpeer)(struct sock *sk);
};
static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -41,11 +40,4 @@ static inline void twsk_destructor(struct sock *sk)
sk->sk_prot->twsk_prot->twsk_destructor(sk);
}
-static inline void *twsk_getpeer(struct sock *sk)
-{
- if (sk->sk_prot->twsk_prot->twsk_getpeer)
- return sk->sk_prot->twsk_prot->twsk_getpeer(sk);
- return NULL;
-}
-
#endif /* _TIMEWAIT_SOCK_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e0a55df5bde8..d9509eb29b80 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1475,6 +1475,8 @@ extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_output_finish(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
+extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler);
+extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler);
extern int xfrm6_extract_header(struct sk_buff *skb);
extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
@@ -1682,13 +1684,11 @@ static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
{
- if ((m->m | m->v) &&
- nla_put(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m))
- goto nla_put_failure;
- return 0;
+ int ret = 0;
-nla_put_failure:
- return -1;
+ if (m->m | m->v)
+ ret = nla_put(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
+ return ret;
}
#endif /* _NET_XFRM_H */