diff options
Diffstat (limited to 'include/net')
31 files changed, 471 insertions, 179 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 9e63e76b20e7..df4ef9453384 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -172,6 +172,9 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, extern int register_inet6addr_notifier(struct notifier_block *nb); extern int unregister_inet6addr_notifier(struct notifier_block *nb); +extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, + struct ipv6_devconf *devconf); + /** * __in6_dev_get - get inet6_dev pointer from netdevice * @dev: network device diff --git a/include/net/af_unix.h b/include/net/af_unix.h index b5f8988e4283..0a996a3517ed 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -53,7 +53,6 @@ struct unix_sock { struct path path; struct mutex readlock; struct sock *peer; - struct sock *other; struct list_head link; atomic_long_t inflight; spinlock_t lock; diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h index b6a6eeb3905f..2581638f4a3d 100644 --- a/include/net/cls_cgroup.h +++ b/include/net/cls_cgroup.h @@ -24,12 +24,12 @@ struct cgroup_cls_state u32 classid; }; -extern void sock_update_classid(struct sock *sk); +extern void sock_update_classid(struct sock *sk, struct task_struct *task); #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP) static inline u32 task_cls_classid(struct task_struct *p) { - int classid; + u32 classid; if (in_interrupt()) return 0; @@ -61,7 +61,7 @@ static inline u32 task_cls_classid(struct task_struct *p) } #endif #else /* !CGROUP_NET_CLS_CGROUP */ -static inline void sock_update_classid(struct sock *sk) +static inline void sock_update_classid(struct sock *sk, struct task_struct *task) { } diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 54be0287eb98..67a8fa098e3a 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -277,7 +277,6 @@ static inline struct sock *inet_lookup_listener(struct net *net, On 64bit targets we combine comparisons with pair of adjacent __be32 fields in the same way. */ -typedef __u32 __bitwise __portpair; #ifdef __BIG_ENDIAN #define INET_COMBINED_PORTS(__sport, __dport) \ ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport))) @@ -287,7 +286,6 @@ typedef __u32 __bitwise __portpair; #endif #if (BITS_PER_LONG == 64) -typedef __u64 __bitwise __addrpair; #ifdef __BIG_ENDIAN #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ const __addrpair __name = (__force __addrpair) ( \ @@ -299,30 +297,34 @@ typedef __u64 __bitwise __addrpair; (((__force __u64)(__be32)(__daddr)) << 32) | \ ((__force __u64)(__be32)(__saddr))); #endif /* __BIG_ENDIAN */ -#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ - (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ - ((*((__addrpair *)&(inet_sk(__sk)->inet_daddr))) == (__cookie)) && \ - ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \ - (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) -#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ - (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ - ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ - ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ - (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) +#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \ + ((inet_sk(__sk)->inet_portpair == (__ports)) && \ + (inet_sk(__sk)->inet_addrpair == (__cookie)) && \ + (!(__sk)->sk_bound_dev_if || \ + ((__sk)->sk_bound_dev_if == (__dif))) && \ + net_eq(sock_net(__sk), (__net))) +#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif)\ + ((inet_twsk(__sk)->tw_portpair == (__ports)) && \ + (inet_twsk(__sk)->tw_addrpair == (__cookie)) && \ + (!(__sk)->sk_bound_dev_if || \ + ((__sk)->sk_bound_dev_if == (__dif))) && \ + net_eq(sock_net(__sk), (__net))) #else /* 32-bit arch */ #define INET_ADDR_COOKIE(__name, __saddr, __daddr) -#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \ - (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ - (inet_sk(__sk)->inet_daddr == (__saddr)) && \ - (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \ - ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \ - (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) -#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ - (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \ - (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ - (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ - ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ - (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) +#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \ + ((inet_sk(__sk)->inet_portpair == (__ports)) && \ + (inet_sk(__sk)->inet_daddr == (__saddr)) && \ + (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \ + (!(__sk)->sk_bound_dev_if || \ + ((__sk)->sk_bound_dev_if == (__dif))) && \ + net_eq(sock_net(__sk), (__net))) +#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \ + ((inet_twsk(__sk)->tw_portpair == (__ports)) && \ + (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ + (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ + (!(__sk)->sk_bound_dev_if || \ + ((__sk)->sk_bound_dev_if == (__dif))) && \ + net_eq(sock_net(__sk), (__net))) #endif /* 64-bit arch */ /* diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 256c1ed2d69a..a4196cbc84ec 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -144,9 +144,11 @@ struct inet_sock { /* Socket demultiplex comparisons on incoming packets. */ #define inet_daddr sk.__sk_common.skc_daddr #define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr +#define inet_addrpair sk.__sk_common.skc_addrpair +#define inet_dport sk.__sk_common.skc_dport +#define inet_num sk.__sk_common.skc_num +#define inet_portpair sk.__sk_common.skc_portpair - __be16 inet_dport; - __u16 inet_num; __be32 inet_saddr; __s16 uc_ttl; __u16 cmsg_flags; @@ -154,6 +156,7 @@ struct inet_sock { __u16 inet_id; struct ip_options_rcu __rcu *inet_opt; + int rx_dst_ifindex; __u8 tos; __u8 min_ttl; __u8 mc_ttl; @@ -170,7 +173,6 @@ struct inet_sock { int uc_index; int mc_index; __be32 mc_addr; - int rx_dst_ifindex; struct ip_mc_socklist __rcu *mc_list; struct inet_cork_full cork; }; diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index ba52c830a7a5..7d658d577368 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -112,6 +112,11 @@ struct inet_timewait_sock { #define tw_net __tw_common.skc_net #define tw_daddr __tw_common.skc_daddr #define tw_rcv_saddr __tw_common.skc_rcv_saddr +#define tw_addrpair __tw_common.skc_addrpair +#define tw_dport __tw_common.skc_dport +#define tw_num __tw_common.skc_num +#define tw_portpair __tw_common.skc_portpair + int tw_timeout; volatile unsigned char tw_substate; unsigned char tw_rcv_wscale; @@ -119,8 +124,6 @@ struct inet_timewait_sock { /* Socket demultiplex comparisons on incoming packets. */ /* these three are in inet_sock */ __be16 tw_sport; - __be16 tw_dport; - __u16 tw_num; kmemcheck_bitfield_begin(flags); /* And these are ours. */ unsigned int tw_ipv6only : 1, diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h index bc1b0fda2b04..652d3d309357 100644 --- a/include/net/ip6_checksum.h +++ b/include/net/ip6_checksum.h @@ -31,6 +31,8 @@ #include <net/ip.h> #include <asm/checksum.h> #include <linux/in6.h> +#include <linux/tcp.h> +#include <linux/ipv6.h> #ifndef _HAVE_ARCH_IPV6_CSUM @@ -91,4 +93,37 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, } #endif + +static __inline__ __sum16 tcp_v6_check(int len, + const struct in6_addr *saddr, + const struct in6_addr *daddr, + __wsum base) +{ + return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); +} + +static inline void __tcp_v6_send_check(struct sk_buff *skb, + const struct in6_addr *saddr, + const struct in6_addr *daddr) +{ + struct tcphdr *th = tcp_hdr(skb); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct tcphdr, check); + } else { + th->check = tcp_v6_check(skb->len, saddr, daddr, + csum_partial(th, th->doff << 2, + skb->csum)); + } +} + +static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + + __tcp_v6_send_check(skb, &np->saddr, &np->daddr); +} + #endif diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 8a2a203eb15d..fdc48a94a063 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -47,6 +47,8 @@ struct fib6_config { unsigned long fc_expires; struct nlattr *fc_mx; int fc_mx_len; + int fc_mp_len; + struct nlattr *fc_mp; struct nl_info fc_nlinfo; }; @@ -99,6 +101,14 @@ struct rt6_info { struct in6_addr rt6i_gateway; + /* Multipath routes: + * siblings is a list of rt6_info that have the the same metric/weight, + * destination, but not the same gateway. nsiblings is just a cache + * to speed up lookup. + */ + struct list_head rt6i_siblings; + unsigned int rt6i_nsiblings; + atomic_t rt6i_ref; /* These are in a separate cache line. */ @@ -107,7 +117,6 @@ struct rt6_info { struct rt6key rt6i_src; struct rt6key rt6i_prefsrc; u32 rt6i_metric; - u32 rt6i_peer_genid; struct inet6_dev *rt6i_idev; unsigned long _rt6i_peer; @@ -203,6 +212,15 @@ static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) dst_hold(new); } +static inline void ip6_rt_put(struct rt6_info *rt) +{ + /* dst_release() accepts a NULL parameter. + * We rely on dst being first structure in struct rt6_info + */ + BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0); + dst_release(&rt->dst); +} + struct fib6_walker_t { struct list_head lh; struct fib6_node *root, *node; diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 5fa2af00634a..27d83183e615 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -1,9 +1,6 @@ #ifndef _NET_IP6_ROUTE_H #define _NET_IP6_ROUTE_H -#define IP6_RT_PRIO_USER 1024 -#define IP6_RT_PRIO_ADDRCONF 256 - struct route_info { __u8 type; __u8 length; diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index ee75ccdf5188..68c69d54d392 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -22,7 +22,10 @@ #include <linux/ip.h> #include <linux/ipv6.h> /* for struct ipv6hdr */ #include <net/ipv6.h> -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#if IS_ENABLED(CONFIG_IP_VS_IPV6) +#include <linux/netfilter_ipv6/ip6_tables.h> +#endif +#if IS_ENABLED(CONFIG_NF_CONNTRACK) #include <net/netfilter/nf_conntrack.h> #endif #include <net/net_namespace.h> /* Netw namespace */ @@ -103,30 +106,117 @@ static inline struct net *seq_file_single_net(struct seq_file *seq) /* Connections' size value needed by ip_vs_ctl.c */ extern int ip_vs_conn_tab_size; - struct ip_vs_iphdr { - int len; - __u8 protocol; + __u32 len; /* IPv4 simply where L4 starts + IPv6 where L4 Transport Header starts */ + __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */ + __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ + __s16 protocol; + __s32 flags; union nf_inet_addr saddr; union nf_inet_addr daddr; }; +/* Dependency to module: nf_defrag_ipv6 */ +#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) +static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) +{ + return skb->nfct_reasm; +} +static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, + int len, void *buffer, + const struct ip_vs_iphdr *ipvsh) +{ + if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb))) + return skb_header_pointer(skb_nfct_reasm(skb), + ipvsh->thoff_reasm, len, buffer); + + return skb_header_pointer(skb, offset, len, buffer); +} +#else +static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) +{ + return NULL; +} +static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, + int len, void *buffer, + const struct ip_vs_iphdr *ipvsh) +{ + return skb_header_pointer(skb, offset, len, buffer); +} +#endif + static inline void -ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr) +ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) +{ + const struct iphdr *iph = nh; + + iphdr->len = iph->ihl * 4; + iphdr->fragoffs = 0; + iphdr->protocol = iph->protocol; + iphdr->saddr.ip = iph->saddr; + iphdr->daddr.ip = iph->daddr; +} + +/* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6. + * IPv6 requires some extra work, as finding proper header position, + * depend on the IPv6 extension headers. + */ +static inline void +ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) { #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { - const struct ipv6hdr *iph = nh; - iphdr->len = sizeof(struct ipv6hdr); - iphdr->protocol = iph->nexthdr; + const struct ipv6hdr *iph = + (struct ipv6hdr *)skb_network_header(skb); iphdr->saddr.in6 = iph->saddr; iphdr->daddr.in6 = iph->daddr; + /* ipv6_find_hdr() updates len, flags, thoff_reasm */ + iphdr->thoff_reasm = 0; + iphdr->len = 0; + iphdr->flags = 0; + iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, + &iphdr->fragoffs, + &iphdr->flags); + /* get proto from re-assembled packet and it's offset */ + if (skb_nfct_reasm(skb)) + iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb), + &iphdr->thoff_reasm, + -1, NULL, NULL); + } else #endif { - const struct iphdr *iph = nh; - iphdr->len = iph->ihl * 4; - iphdr->protocol = iph->protocol; + const struct iphdr *iph = + (struct iphdr *)skb_network_header(skb); + iphdr->len = iph->ihl * 4; + iphdr->fragoffs = 0; + iphdr->protocol = iph->protocol; + iphdr->saddr.ip = iph->saddr; + iphdr->daddr.ip = iph->daddr; + } +} + +/* This function is a faster version of ip_vs_fill_iph_skb(). + * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()). + * This is used by the some of the ip_vs_*_schedule() functions. + * (Mostly done to avoid ABI breakage of external schedulers) + */ +static inline void +ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb, + struct ip_vs_iphdr *iphdr) +{ +#ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { + const struct ipv6hdr *iph = + (struct ipv6hdr *)skb_network_header(skb); + iphdr->saddr.in6 = iph->saddr; + iphdr->daddr.in6 = iph->daddr; + } else +#endif + { + const struct iphdr *iph = + (struct iphdr *)skb_network_header(skb); iphdr->saddr.ip = iph->saddr; iphdr->daddr.ip = iph->daddr; } @@ -165,7 +255,7 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len, int len; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) - len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]", + len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]", &addr->in6) + 1; else #endif @@ -398,27 +488,26 @@ struct ip_vs_protocol { int (*conn_schedule)(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, - int *verdict, struct ip_vs_conn **cpp); + int *verdict, struct ip_vs_conn **cpp, + struct ip_vs_iphdr *iph); struct ip_vs_conn * (*conn_in_get)(int af, const struct sk_buff *skb, const struct ip_vs_iphdr *iph, - unsigned int proto_off, int inverse); struct ip_vs_conn * (*conn_out_get)(int af, const struct sk_buff *skb, const struct ip_vs_iphdr *iph, - unsigned int proto_off, int inverse); - int (*snat_handler)(struct sk_buff *skb, - struct ip_vs_protocol *pp, struct ip_vs_conn *cp); + int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp, + struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); - int (*dnat_handler)(struct sk_buff *skb, - struct ip_vs_protocol *pp, struct ip_vs_conn *cp); + int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp, + struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); int (*csum_check)(int af, struct sk_buff *skb, struct ip_vs_protocol *pp); @@ -518,7 +607,7 @@ struct ip_vs_conn { NF_ACCEPT can be returned when destination is local. */ int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); /* Note: we can group the following members into a structure, in order to save more space, and the following members are @@ -769,13 +858,11 @@ struct ip_vs_app { struct ip_vs_conn * (*conn_in_get)(const struct sk_buff *skb, struct ip_vs_app *app, - const struct iphdr *iph, unsigned int proto_off, - int inverse); + const struct iphdr *iph, int inverse); struct ip_vs_conn * (*conn_out_get)(const struct sk_buff *skb, struct ip_vs_app *app, - const struct iphdr *iph, unsigned int proto_off, - int inverse); + const struct iphdr *iph, int inverse); int (*state_transition)(struct ip_vs_conn *cp, int direction, const struct sk_buff *skb, @@ -1074,14 +1161,12 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p); struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, const struct ip_vs_iphdr *iph, - unsigned int proto_off, int inverse); struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p); struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb, const struct ip_vs_iphdr *iph, - unsigned int proto_off, int inverse); /* put back the conn without restarting its timer */ @@ -1254,9 +1339,10 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name); extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler); extern struct ip_vs_conn * ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, - struct ip_vs_proto_data *pd, int *ignored); + struct ip_vs_proto_data *pd, int *ignored, + struct ip_vs_iphdr *iph); extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, - struct ip_vs_proto_data *pd); + struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph); extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); @@ -1315,33 +1401,38 @@ extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst, /* * Various IPVS packet transmitters (from ip_vs_xmit.c) */ -extern int ip_vs_null_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_bypass_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_nat_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_tunnel_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_dr_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_icmp_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, - int offset, unsigned int hooknum); +extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, + struct ip_vs_iphdr *iph); +extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, + struct ip_vs_iphdr *iph); +extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, int offset, + unsigned int hooknum, struct ip_vs_iphdr *iph); extern void ip_vs_dst_reset(struct ip_vs_dest *dest); #ifdef CONFIG_IP_VS_IPV6 -extern int ip_vs_bypass_xmit_v6 -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_nat_xmit_v6 -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_tunnel_xmit_v6 -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_dr_xmit_v6 -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); -extern int ip_vs_icmp_xmit_v6 -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, - int offset, unsigned int hooknum); +extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, + struct ip_vs_iphdr *iph); +extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, + struct ip_vs_iphdr *iph); +extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, + struct ip_vs_iphdr *iph); +extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); +extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, int offset, + unsigned int hooknum, struct ip_vs_iphdr *iph); #endif #ifdef CONFIG_SYSCTL diff --git a/include/net/ipip.h b/include/net/ipip.h index ddc077c51f32..21947cf4fa46 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -48,25 +48,27 @@ struct ip_tunnel_prl_entry { struct rcu_head rcu_head; }; -#define __IPTUNNEL_XMIT(stats1, stats2) do { \ - int err; \ - int pkt_len = skb->len - skb_transport_offset(skb); \ - \ - skb->ip_summed = CHECKSUM_NONE; \ - ip_select_ident(iph, &rt->dst, NULL); \ - \ - err = ip_local_out(skb); \ - if (likely(net_xmit_eval(err) == 0)) { \ - u64_stats_update_begin(&(stats1)->syncp); \ - (stats1)->tx_bytes += pkt_len; \ - (stats1)->tx_packets++; \ - u64_stats_update_end(&(stats1)->syncp); \ - } else { \ - (stats2)->tx_errors++; \ - (stats2)->tx_aborted_errors++; \ - } \ -} while (0) +static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int err; + struct iphdr *iph = ip_hdr(skb); + int pkt_len = skb->len - skb_transport_offset(skb); + struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats); -#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats) + nf_reset(skb); + skb->ip_summed = CHECKSUM_NONE; + ip_select_ident(iph, skb_dst(skb), NULL); + + err = ip_local_out(skb); + if (likely(net_xmit_eval(err) == 0)) { + u64_stats_update_begin(&tstats->syncp); + tstats->tx_bytes += pkt_len; + tstats->tx_packets++; + u64_stats_update_end(&tstats->syncp); + } else { + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; + } +} #endif diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 979bf6c13141..5af66b26ebdd 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -271,6 +271,15 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb); +static inline bool ipv6_accept_ra(struct inet6_dev *idev) +{ + /* If forwarding is enabled, RA are not accepted unless the special + * hybrid mode (accept_ra=2) is enabled. + */ + return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 : + idev->cnf.accept_ra; +} + #if IS_ENABLED(CONFIG_IPV6) static inline int ip6_frag_nqueues(struct net *net) { @@ -630,6 +639,16 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start, extern bool ipv6_ext_hdr(u8 nexthdr); +enum { + IP6_FH_F_FRAG = (1 << 0), + IP6_FH_F_AUTH = (1 << 1), + IP6_FH_F_SKIP_RH = (1 << 2), +}; + +/* find specified header and get offset to it */ +extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, + int target, unsigned short *fragoff, int *fragflg); + extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6, diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 95e646641184..c5a43f56b796 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -23,6 +23,7 @@ #endif #include <net/netns/xfrm.h> +struct user_namespace; struct proc_dir_entry; struct net_device; struct sock; @@ -53,6 +54,8 @@ struct net { struct list_head cleanup_list; /* namespaces on death row */ struct list_head exit_list; /* Use only net_mutex */ + struct user_namespace *user_ns; /* Owning user namespace */ + struct proc_dir_entry *proc_net; struct proc_dir_entry *proc_net_stat; @@ -126,16 +129,21 @@ struct net { /* Init's network namespace */ extern struct net init_net; -#ifdef CONFIG_NET -extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns); - -#else /* CONFIG_NET */ -static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns) +#ifdef CONFIG_NET_NS +extern struct net *copy_net_ns(unsigned long flags, + struct user_namespace *user_ns, struct net *old_net); + +#else /* CONFIG_NET_NS */ +#include <linux/sched.h> +#include <linux/nsproxy.h> +static inline struct net *copy_net_ns(unsigned long flags, + struct user_namespace *user_ns, struct net *old_net) { - /* There is nothing to copy so this is a noop */ - return net_ns; + if (flags & CLONE_NEWNET) + return ERR_PTR(-EINVAL); + return old_net; } -#endif /* CONFIG_NET */ +#endif /* CONFIG_NET_NS */ extern struct list_head net_namespace_list; diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index f1494feba79f..caca0c4d6b4b 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -182,7 +182,7 @@ __nf_conntrack_find(struct net *net, u16 zone, extern int nf_conntrack_hash_check_insert(struct nf_conn *ct); extern void nf_ct_delete_from_lists(struct nf_conn *ct); -extern void nf_ct_insert_dying_list(struct nf_conn *ct); +extern void nf_ct_dying_timeout(struct nf_conn *ct); extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report); diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index bd8eea720f2e..ad14a799fd2e 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -68,4 +68,19 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) #endif } +static inline bool nf_nat_oif_changed(unsigned int hooknum, + enum ip_conntrack_info ctinfo, + struct nf_conn_nat *nat, + const struct net_device *out) +{ +#if IS_ENABLED(CONFIG_IP_NF_TARGET_MASQUERADE) || \ + IS_ENABLED(CONFIG_IP6_NF_TARGET_MASQUERADE) + return nat->masq_index && hooknum == NF_INET_POST_ROUTING && + CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL && + nat->masq_index != out->ifindex; +#else + return false; +#endif +} + #endif diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 252fd1010b77..fb1c0be38b6d 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -21,14 +21,10 @@ struct nf_queue_entry { struct nf_queue_handler { int (*outfn)(struct nf_queue_entry *entry, unsigned int queuenum); - char *name; }; -extern int nf_register_queue_handler(u_int8_t pf, - const struct nf_queue_handler *qh); -extern int nf_unregister_queue_handler(u_int8_t pf, - const struct nf_queue_handler *qh); -extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); +void nf_register_queue_handler(const struct nf_queue_handler *qh); +void nf_unregister_queue_handler(void); extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); #endif /* _NF_QUEUE_H */ diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h index 5e5eb1f9f14b..3573a81815ad 100644 --- a/include/net/netns/sctp.h +++ b/include/net/netns/sctp.h @@ -62,6 +62,9 @@ struct netns_sctp { /* Whether Cookie Preservative is enabled(1) or not(0) */ int cookie_preserve_enable; + /* The namespace default hmac alg */ + char *sctp_hmac_alg; + /* Valid.Cookie.Life - 60 seconds */ unsigned int valid_cookie_life; diff --git a/include/net/protocol.h b/include/net/protocol.h index 929528c73fe8..047c0476c0a0 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -25,9 +25,11 @@ #define _PROTOCOL_H #include <linux/in6.h> +#include <linux/skbuff.h> #if IS_ENABLED(CONFIG_IPV6) #include <linux/ipv6.h> #endif +#include <linux/netdevice.h> /* 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 @@ -40,12 +42,6 @@ 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); - struct sk_buff *(*gso_segment)(struct sk_buff *skb, - netdev_features_t features); - struct sk_buff **(*gro_receive)(struct sk_buff **head, - struct sk_buff *skb); - int (*gro_complete)(struct sk_buff *skb); unsigned int no_policy:1, netns_ok:1; }; @@ -60,23 +56,20 @@ struct inet6_protocol { struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info); - - int (*gso_send_check)(struct sk_buff *skb); - struct sk_buff *(*gso_segment)(struct sk_buff *skb, - netdev_features_t features); - struct sk_buff **(*gro_receive)(struct sk_buff **head, - struct sk_buff *skb); - int (*gro_complete)(struct sk_buff *skb); - unsigned int flags; /* INET6_PROTO_xxx */ }; #define INET6_PROTO_NOPOLICY 0x1 #define INET6_PROTO_FINAL 0x2 -/* This should be set for any extension header which is compatible with GSO. */ -#define INET6_PROTO_GSO_EXTHDR 0x4 #endif +struct net_offload { + struct offload_callbacks callbacks; + unsigned int flags; /* Flags used by IPv6 for now */ +}; +/* This should be set for any extension header which is compatible with GSO. */ +#define INET6_PROTO_GSO_EXTHDR 0x1 + /* This is used to register socket interfaces for IP protocols. */ struct inet_protosw { struct list_head list; @@ -96,6 +89,8 @@ struct inet_protosw { #define INET_PROTOSW_ICSK 0x04 /* Is this an inet_connection_sock? */ extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS]; +extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS]; +extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS]; #if IS_ENABLED(CONFIG_IPV6) extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; @@ -103,6 +98,8 @@ extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num); extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num); +extern int inet_add_offload(const struct net_offload *prot, unsigned char num); +extern int inet_del_offload(const struct net_offload *prot, unsigned char num); extern void inet_register_protosw(struct inet_protosw *p); extern void inet_unregister_protosw(struct inet_protosw *p); @@ -112,5 +109,7 @@ extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char n extern int inet6_register_protosw(struct inet_protosw *p); extern void inet6_unregister_protosw(struct inet_protosw *p); #endif +extern int inet6_add_offload(const struct net_offload *prot, unsigned char num); +extern int inet6_del_offload(const struct net_offload *prot, unsigned char num); #endif /* _PROTOCOL_H */ diff --git a/include/net/request_sock.h b/include/net/request_sock.h index b01d8dd9ee7c..a51dbd17c2de 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -49,13 +49,16 @@ struct request_sock_ops { struct request_sock *req); }; +extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req); + /* struct request_sock - mini sock to represent a connection request */ struct request_sock { struct request_sock *dl_next; /* Must be first member! */ u16 mss; - u8 retrans; - u8 cookie_ts; /* syncookie: encode tcpopts in timestamp */ + u8 num_retrans; /* number of retransmits */ + u8 cookie_ts:1; /* syncookie: encode tcpopts in timestamp */ + u8 num_timeout:7; /* number of timeouts */ /* The following two fields can be easily recomputed I think -AK */ u32 window_clamp; /* window clamp at creation time */ u32 rcv_wnd; /* rcv_wnd offered first time */ @@ -231,7 +234,7 @@ static inline int reqsk_queue_removed(struct request_sock_queue *queue, { struct listen_sock *lopt = queue->listen_opt; - if (req->retrans == 0) + if (req->num_timeout == 0) --lopt->qlen_young; return --lopt->qlen; @@ -269,7 +272,8 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue, struct listen_sock *lopt = queue->listen_opt; req->expires = jiffies + timeout; - req->retrans = 0; + req->num_retrans = 0; + req->num_timeout = 0; req->sk = NULL; req->dl_next = lopt->syn_table[hash]; diff --git a/include/net/route.h b/include/net/route.h index bc40b633a5c4..2ea40c1b5e00 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -198,10 +198,13 @@ struct in_ifaddr; extern void fib_add_ifaddr(struct in_ifaddr *); extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *); -static inline void ip_rt_put(struct rtable * rt) +static inline void ip_rt_put(struct rtable *rt) { - if (rt) - dst_release(&rt->dst); + /* dst_release() accepts a NULL parameter. + * We rely on dst being first structure in struct rtable + */ + BUILD_BUG_ON(offsetof(struct rtable, dst) != 0); + dst_release(&rt->dst); } #define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3) diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 6b00c4fc4291..5a15fabd6a75 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -125,7 +125,7 @@ extern void rtnl_af_unregister(struct rtnl_af_ops *ops); extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]); -extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net, +extern struct net_device *rtnl_create_link(struct net *net, char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]); extern int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm); diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 712b3bebeda7..35247271e557 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -130,8 +130,6 @@ typedef union { __be16 err; sctp_state_t state; sctp_event_timeout_t to; - unsigned long zero; - void *ptr; struct sctp_chunk *chunk; struct sctp_association *asoc; struct sctp_transport *transport; @@ -154,23 +152,15 @@ typedef union { * which takes an __s32 and returns a sctp_arg_t containing the * __s32. So, after foo = SCTP_I32(arg), foo.i32 == arg. */ -static inline sctp_arg_t SCTP_NULL(void) -{ - sctp_arg_t retval; retval.ptr = NULL; return retval; -} -static inline sctp_arg_t SCTP_NOFORCE(void) -{ - sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval; -} -static inline sctp_arg_t SCTP_FORCE(void) -{ - sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval; -} #define SCTP_ARG_CONSTRUCTOR(name, type, elt) \ static inline sctp_arg_t \ SCTP_## name (type arg) \ -{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; } +{ sctp_arg_t retval;\ + memset(&retval, 0, sizeof(sctp_arg_t));\ + retval.elt = arg;\ + return retval;\ +} SCTP_ARG_CONSTRUCTOR(I32, __s32, i32) SCTP_ARG_CONSTRUCTOR(U32, __u32, u32) @@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR, int, error) SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */ SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) -SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc) SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport) @@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet) SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh) SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg) +static inline sctp_arg_t SCTP_FORCE(void) +{ + return SCTP_I32(1); +} + +static inline sctp_arg_t SCTP_NOFORCE(void) +{ + return SCTP_I32(0); +} + +static inline sctp_arg_t SCTP_NULL(void) +{ + sctp_arg_t retval; + memset(&retval, 0, sizeof(sctp_arg_t)); + return retval; +} + typedef struct { sctp_arg_t obj; sctp_verb_t verb; diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index d053d2e99876..c29707d654c0 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -312,14 +312,6 @@ enum { SCTP_MAX_GABS = 16 }; * functions simpler to write. */ -#if defined (CONFIG_SCTP_HMAC_MD5) -#define SCTP_COOKIE_HMAC_ALG "hmac(md5)" -#elif defined (CONFIG_SCTP_HMAC_SHA1) -#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)" -#else -#define SCTP_COOKIE_HMAC_ALG NULL -#endif - /* These return values describe the success or failure of a number of * routines which form the lower interface to SCTP_outqueue. */ diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 9c6414f553f9..7fdf298a47ef 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -272,6 +272,18 @@ struct sctp_mib { unsigned long mibs[SCTP_MIB_MAX]; }; +/* helper function to track stats about max rto and related transport */ +static inline void sctp_max_rto(struct sctp_association *asoc, + struct sctp_transport *trans) +{ + if (asoc->stats.max_obs_rto < (__u64)trans->rto) { + asoc->stats.max_obs_rto = trans->rto; + memset(&asoc->stats.obs_rto_ipaddr, 0, + sizeof(struct sockaddr_storage)); + memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr, + trans->af_specific->sockaddr_len); + } +} /* Print debugging messages. */ #if SCTP_DEBUG diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index b5887e1677e4..2a82d1384706 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -234,6 +234,8 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *, struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *, const struct sctp_chunk *, struct sctp_paramhdr *); +struct sctp_chunk *sctp_make_violation_max_retrans(const struct sctp_association *, + const struct sctp_chunk *); struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *, const struct sctp_transport *); struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *, diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 64158aa1bb5f..c2521016d646 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -177,6 +177,7 @@ struct sctp_sock { /* Access to HMAC transform. */ struct crypto_hash *hmac; + char *sctp_hmac_alg; /* What is our base endpointer? */ struct sctp_endpoint *ep; @@ -1311,6 +1312,40 @@ struct sctp_inithdr_host { __u32 initial_tsn; }; +/* SCTP_GET_ASSOC_STATS counters */ +struct sctp_priv_assoc_stats { + /* Maximum observed rto in the association during subsequent + * observations. Value is set to 0 if no RTO measurement took place + * The transport where the max_rto was observed is returned in + * obs_rto_ipaddr + */ + struct sockaddr_storage obs_rto_ipaddr; + __u64 max_obs_rto; + /* Total In and Out SACKs received and sent */ + __u64 isacks; + __u64 osacks; + /* Total In and Out packets received and sent */ + __u64 opackets; + __u64 ipackets; + /* Total retransmitted chunks */ + __u64 rtxchunks; + /* TSN received > next expected */ + __u64 outofseqtsns; + /* Duplicate Chunks received */ + __u64 idupchunks; + /* Gap Ack Blocks received */ + __u64 gapcnt; + /* Unordered data chunks sent and received */ + __u64 ouodchunks; + __u64 iuodchunks; + /* Ordered data chunks sent and received */ + __u64 oodchunks; + __u64 iodchunks; + /* Control chunks sent and received */ + __u64 octrlchunks; + __u64 ictrlchunks; +}; + /* RFC2960 * * 12. Recommended Transmission Control Block (TCB) Parameters @@ -1829,6 +1864,8 @@ struct sctp_association { __u8 need_ecne:1, /* Need to send an ECNE Chunk? */ temp:1; /* Is it a temporary association? */ + + struct sctp_priv_assoc_stats stats; }; diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h index 2e5ee0d8458d..ff1b8ba73ab1 100644 --- a/include/net/sctp/ulpqueue.h +++ b/include/net/sctp/ulpqueue.h @@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev); void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t); /* Perform partial delivery. */ -void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t); +void sctp_ulpq_partial_delivery(struct sctp_ulpq *, gfp_t); /* Abort the partial delivery. */ void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 1b02d7ad453b..9a0ae091366d 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -107,6 +107,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_GET_LOCAL_ADDRS 109 /* Get all local address. */ #define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */ #define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */ +#define SCTP_GET_ASSOC_STATS 112 /* Read only */ /* * 5.2.1 SCTP Initiation Structure (SCTP_INIT) @@ -719,6 +720,32 @@ struct sctp_getaddrs { __u8 addrs[0]; /*output, variable size*/ }; +/* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves + * association stats. All stats are counts except sas_maxrto and + * sas_obs_rto_ipaddr. maxrto is the max observed rto + transport since + * the last call. Will return 0 when RTO was not update since last call + */ +struct sctp_assoc_stats { + sctp_assoc_t sas_assoc_id; /* Input */ + /* Transport of observed max RTO */ + struct sockaddr_storage sas_obs_rto_ipaddr; + __u64 sas_maxrto; /* Maximum Observed RTO for period */ + __u64 sas_isacks; /* SACKs received */ + __u64 sas_osacks; /* SACKs sent */ + __u64 sas_opackets; /* Packets sent */ + __u64 sas_ipackets; /* Packets received */ + __u64 sas_rtxchunks; /* Retransmitted Chunks */ + __u64 sas_outofseqtsns;/* TSN received > next expected */ + __u64 sas_idupchunks; /* Dups received (ordered+unordered) */ + __u64 sas_gapcnt; /* Gap Acknowledgements Received */ + __u64 sas_ouodchunks; /* Unordered data chunks sent */ + __u64 sas_iuodchunks; /* Unordered data chunks received */ + __u64 sas_oodchunks; /* Ordered data chunks sent */ + __u64 sas_iodchunks; /* Ordered data chunks received */ + __u64 sas_octrlchunks; /* Control chunks sent */ + __u64 sas_ictrlchunks; /* Control chunks received */ +}; + /* These are bit fields for msghdr->msg_flags. See section 5.1. */ /* On user space Linux, these live in <bits/socket.h> as an enum. */ enum sctp_msg_flags { diff --git a/include/net/sock.h b/include/net/sock.h index c945fba4f543..0a9a01a5b0d7 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -126,12 +126,17 @@ struct sock; struct proto; struct net; +typedef __u32 __bitwise __portpair; +typedef __u64 __bitwise __addrpair; + /** * struct sock_common - minimal network layer representation of sockets * @skc_daddr: Foreign IPv4 addr * @skc_rcv_saddr: Bound local IPv4 addr * @skc_hash: hash value used with various protocol lookup tables * @skc_u16hashes: two u16 hash values used by UDP lookup tables + * @skc_dport: placeholder for inet_dport/tw_dport + * @skc_num: placeholder for inet_num/tw_num * @skc_family: network address family * @skc_state: Connection state * @skc_reuse: %SO_REUSEADDR setting @@ -149,16 +154,29 @@ struct net; * for struct sock and struct inet_timewait_sock. */ struct sock_common { - /* skc_daddr and skc_rcv_saddr must be grouped : - * cf INET_MATCH() and INET_TW_MATCH() + /* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned + * address on 64bit arches : cf INET_MATCH() and INET_TW_MATCH() */ - __be32 skc_daddr; - __be32 skc_rcv_saddr; - + union { + __addrpair skc_addrpair; + struct { + __be32 skc_daddr; + __be32 skc_rcv_saddr; + }; + }; union { unsigned int skc_hash; __u16 skc_u16hashes[2]; }; + /* skc_dport && skc_num must be grouped as well */ + union { + __portpair skc_portpair; + struct { + __be16 skc_dport; + __u16 skc_num; + }; + }; + unsigned short skc_family; volatile unsigned char skc_state; unsigned char skc_reuse; diff --git a/include/net/tcp.h b/include/net/tcp.h index 6feeccd83dd7..3202bde2a741 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -369,7 +369,6 @@ 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); 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); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 6f0ba01afe73..63445ede48bb 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1351,7 +1351,7 @@ struct xfrm6_tunnel { }; extern void xfrm_init(void); -extern void xfrm4_init(int rt_hash_size); +extern void xfrm4_init(void); extern int xfrm_state_init(struct net *net); extern void xfrm_state_fini(struct net *net); extern void xfrm4_state_init(void); |