aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 20:41:19 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 20:41:19 -0500
commitf5af19d10d151c5a2afae3306578f485c244db25 (patch)
tree54e762e70afb664d14152e6bcf89a48be3fb9c13 /net/ipv4
parent0d695d6d8bc1ed39f20c9ce115abf0129b27cb6f (diff)
parent19334920eaf7df3f69950b040ede6c7598425a5b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking updates from David Miller: 1) Missing netlink attribute validation in nft_lookup, from Patrick McHardy. 2) Restrict ipv6 partial checksum handling to UDP, since that's the only case it works for. From Vlad Yasevich. 3) Clear out silly device table sentinal macros used by SSB and BCMA drivers. From Joe Perches. 4) Make sure the remote checksum code never creates a situation where the remote checksum is applied yet the tunneling metadata describing the remote checksum transformation is still present. Otherwise an external entity might see this and apply the checksum again. From Tom Herbert. 5) Use msecs_to_jiffies() where applicable, from Nicholas Mc Guire. 6) Don't explicitly initialize timer struct fields, use setup_timer() and mod_timer() instead. From Vaishali Thakkar. 7) Don't invoke tg3_halt() without the tp->lock held, from Jun'ichi Nomura. 8) Missing __percpu annotation in ipvlan driver, from Eric Dumazet. 9) Don't potentially perform skb_get() on shared skbs, also from Eric Dumazet. 10) Fix COW'ing of metrics for non-DST_HOST routes in ipv6, from Martin KaFai Lau. 11) Fix merge resolution error between the iov_iter changes in vhost and some bug fixes that occurred at the same time. From Jason Wang. 12) If rtnl_configure_link() fails we have to perform a call to ->dellink() before unregistering the device. From WANG Cong. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (39 commits) net: dsa: Set valid phy interface type rtnetlink: call ->dellink on failure when ->newlink exists com20020-pci: add support for eae single card vhost_net: fix wrong iter offset when setting number of buffers net: spelling fixes net/core: Fix warning while make xmldocs caused by dev.c net: phy: micrel: disable NAND-tree for KSZ8021, KSZ8031, KSZ8051, KSZ8081 ipv6: fix ipv6_cow_metrics for non DST_HOST case openvswitch: Fix key serialization. r8152: restore hw settings hso: fix rx parsing logic when skb allocation fails tcp: make sure skb is not shared before using skb_get() bridge: netfilter: Move sysctl-specific error code inside #ifdef ipv6: fix possible deadlock in ip6_fl_purge / ip6_fl_gc ipvlan: add a missing __percpu pcpu_stats tg3: Hold tp->lock before calling tg3_halt() from tg3_init_one() bgmac: fix device initialization on Northstar SoCs (condition typo) qlcnic: Delete existing multicast MAC list before adding new net/mlx5_core: Fix configuration of log_uar_page_sz sunvnet: don't change gso data on clones ...
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/devinet.c2
-rw-r--r--net/ipv4/fou.c42
-rw-r--r--net/ipv4/tcp_fastopen.c32
-rw-r--r--net/ipv4/udp_offload.c13
4 files changed, 66 insertions, 23 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index f0b4a31d7bd6..3a8985c94581 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1186,7 +1186,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
1186no_in_dev: 1186no_in_dev:
1187 1187
1188 /* Not loopback addresses on loopback should be preferred 1188 /* Not loopback addresses on loopback should be preferred
1189 in this case. It is importnat that lo is the first interface 1189 in this case. It is important that lo is the first interface
1190 in dev_base list. 1190 in dev_base list.
1191 */ 1191 */
1192 for_each_netdev_rcu(net, dev) { 1192 for_each_netdev_rcu(net, dev) {
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 92ddea1e6457..ff069f6597ac 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -22,14 +22,18 @@ static LIST_HEAD(fou_list);
22struct fou { 22struct fou {
23 struct socket *sock; 23 struct socket *sock;
24 u8 protocol; 24 u8 protocol;
25 u8 flags;
25 u16 port; 26 u16 port;
26 struct udp_offload udp_offloads; 27 struct udp_offload udp_offloads;
27 struct list_head list; 28 struct list_head list;
28}; 29};
29 30
31#define FOU_F_REMCSUM_NOPARTIAL BIT(0)
32
30struct fou_cfg { 33struct fou_cfg {
31 u16 type; 34 u16 type;
32 u8 protocol; 35 u8 protocol;
36 u8 flags;
33 struct udp_port_cfg udp_config; 37 struct udp_port_cfg udp_config;
34}; 38};
35 39
@@ -64,24 +68,20 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
64} 68}
65 69
66static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, 70static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
67 void *data, size_t hdrlen, u8 ipproto) 71 void *data, size_t hdrlen, u8 ipproto,
72 bool nopartial)
68{ 73{
69 __be16 *pd = data; 74 __be16 *pd = data;
70 size_t start = ntohs(pd[0]); 75 size_t start = ntohs(pd[0]);
71 size_t offset = ntohs(pd[1]); 76 size_t offset = ntohs(pd[1]);
72 size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); 77 size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
73 78
74 if (skb->remcsum_offload) {
75 /* Already processed in GRO path */
76 skb->remcsum_offload = 0;
77 return guehdr;
78 }
79
80 if (!pskb_may_pull(skb, plen)) 79 if (!pskb_may_pull(skb, plen))
81 return NULL; 80 return NULL;
82 guehdr = (struct guehdr *)&udp_hdr(skb)[1]; 81 guehdr = (struct guehdr *)&udp_hdr(skb)[1];
83 82
84 skb_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset); 83 skb_remcsum_process(skb, (void *)guehdr + hdrlen,
84 start, offset, nopartial);
85 85
86 return guehdr; 86 return guehdr;
87} 87}
@@ -142,7 +142,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
142 142
143 if (flags & GUE_PFLAG_REMCSUM) { 143 if (flags & GUE_PFLAG_REMCSUM) {
144 guehdr = gue_remcsum(skb, guehdr, data + doffset, 144 guehdr = gue_remcsum(skb, guehdr, data + doffset,
145 hdrlen, guehdr->proto_ctype); 145 hdrlen, guehdr->proto_ctype,
146 !!(fou->flags &
147 FOU_F_REMCSUM_NOPARTIAL));
146 if (!guehdr) 148 if (!guehdr)
147 goto drop; 149 goto drop;
148 150
@@ -214,7 +216,8 @@ out_unlock:
214 216
215static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, 217static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
216 struct guehdr *guehdr, void *data, 218 struct guehdr *guehdr, void *data,
217 size_t hdrlen, u8 ipproto) 219 size_t hdrlen, u8 ipproto,
220 struct gro_remcsum *grc, bool nopartial)
218{ 221{
219 __be16 *pd = data; 222 __be16 *pd = data;
220 size_t start = ntohs(pd[0]); 223 size_t start = ntohs(pd[0]);
@@ -222,7 +225,7 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
222 size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); 225 size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
223 226
224 if (skb->remcsum_offload) 227 if (skb->remcsum_offload)
225 return guehdr; 228 return NULL;
226 229
227 if (!NAPI_GRO_CB(skb)->csum_valid) 230 if (!NAPI_GRO_CB(skb)->csum_valid)
228 return NULL; 231 return NULL;
@@ -234,7 +237,8 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
234 return NULL; 237 return NULL;
235 } 238 }
236 239
237 skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen, start, offset); 240 skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen,
241 start, offset, grc, nopartial);
238 242
239 skb->remcsum_offload = 1; 243 skb->remcsum_offload = 1;
240 244
@@ -254,6 +258,10 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
254 void *data; 258 void *data;
255 u16 doffset = 0; 259 u16 doffset = 0;
256 int flush = 1; 260 int flush = 1;
261 struct fou *fou = container_of(uoff, struct fou, udp_offloads);
262 struct gro_remcsum grc;
263
264 skb_gro_remcsum_init(&grc);
257 265
258 off = skb_gro_offset(skb); 266 off = skb_gro_offset(skb);
259 len = off + sizeof(*guehdr); 267 len = off + sizeof(*guehdr);
@@ -295,7 +303,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
295 if (flags & GUE_PFLAG_REMCSUM) { 303 if (flags & GUE_PFLAG_REMCSUM) {
296 guehdr = gue_gro_remcsum(skb, off, guehdr, 304 guehdr = gue_gro_remcsum(skb, off, guehdr,
297 data + doffset, hdrlen, 305 data + doffset, hdrlen,
298 guehdr->proto_ctype); 306 guehdr->proto_ctype, &grc,
307 !!(fou->flags &
308 FOU_F_REMCSUM_NOPARTIAL));
299 if (!guehdr) 309 if (!guehdr)
300 goto out; 310 goto out;
301 311
@@ -345,6 +355,7 @@ out_unlock:
345 rcu_read_unlock(); 355 rcu_read_unlock();
346out: 356out:
347 NAPI_GRO_CB(skb)->flush |= flush; 357 NAPI_GRO_CB(skb)->flush |= flush;
358 skb_gro_remcsum_cleanup(skb, &grc);
348 359
349 return pp; 360 return pp;
350} 361}
@@ -455,6 +466,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
455 466
456 sk = sock->sk; 467 sk = sock->sk;
457 468
469 fou->flags = cfg->flags;
458 fou->port = cfg->udp_config.local_udp_port; 470 fou->port = cfg->udp_config.local_udp_port;
459 471
460 /* Initial for fou type */ 472 /* Initial for fou type */
@@ -541,6 +553,7 @@ static struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
541 [FOU_ATTR_AF] = { .type = NLA_U8, }, 553 [FOU_ATTR_AF] = { .type = NLA_U8, },
542 [FOU_ATTR_IPPROTO] = { .type = NLA_U8, }, 554 [FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
543 [FOU_ATTR_TYPE] = { .type = NLA_U8, }, 555 [FOU_ATTR_TYPE] = { .type = NLA_U8, },
556 [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, },
544}; 557};
545 558
546static int parse_nl_config(struct genl_info *info, 559static int parse_nl_config(struct genl_info *info,
@@ -571,6 +584,9 @@ static int parse_nl_config(struct genl_info *info,
571 if (info->attrs[FOU_ATTR_TYPE]) 584 if (info->attrs[FOU_ATTR_TYPE])
572 cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); 585 cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]);
573 586
587 if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL])
588 cfg->flags |= FOU_F_REMCSUM_NOPARTIAL;
589
574 return 0; 590 return 0;
575} 591}
576 592
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index 53db2c309572..ea82fd492c1b 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -134,6 +134,7 @@ static bool tcp_fastopen_create_child(struct sock *sk,
134 struct tcp_sock *tp; 134 struct tcp_sock *tp;
135 struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; 135 struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
136 struct sock *child; 136 struct sock *child;
137 u32 end_seq;
137 138
138 req->num_retrans = 0; 139 req->num_retrans = 0;
139 req->num_timeout = 0; 140 req->num_timeout = 0;
@@ -185,20 +186,35 @@ static bool tcp_fastopen_create_child(struct sock *sk,
185 186
186 /* Queue the data carried in the SYN packet. We need to first 187 /* Queue the data carried in the SYN packet. We need to first
187 * bump skb's refcnt because the caller will attempt to free it. 188 * bump skb's refcnt because the caller will attempt to free it.
189 * Note that IPv6 might also have used skb_get() trick
190 * in tcp_v6_conn_request() to keep this SYN around (treq->pktopts)
191 * So we need to eventually get a clone of the packet,
192 * before inserting it in sk_receive_queue.
188 * 193 *
189 * XXX (TFO) - we honor a zero-payload TFO request for now, 194 * XXX (TFO) - we honor a zero-payload TFO request for now,
190 * (any reason not to?) but no need to queue the skb since 195 * (any reason not to?) but no need to queue the skb since
191 * there is no data. How about SYN+FIN? 196 * there is no data. How about SYN+FIN?
192 */ 197 */
193 if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1) { 198 end_seq = TCP_SKB_CB(skb)->end_seq;
194 skb = skb_get(skb); 199 if (end_seq != TCP_SKB_CB(skb)->seq + 1) {
195 skb_dst_drop(skb); 200 struct sk_buff *skb2;
196 __skb_pull(skb, tcp_hdr(skb)->doff * 4); 201
197 skb_set_owner_r(skb, child); 202 if (unlikely(skb_shared(skb)))
198 __skb_queue_tail(&child->sk_receive_queue, skb); 203 skb2 = skb_clone(skb, GFP_ATOMIC);
199 tp->syn_data_acked = 1; 204 else
205 skb2 = skb_get(skb);
206
207 if (likely(skb2)) {
208 skb_dst_drop(skb2);
209 __skb_pull(skb2, tcp_hdrlen(skb));
210 skb_set_owner_r(skb2, child);
211 __skb_queue_tail(&child->sk_receive_queue, skb2);
212 tp->syn_data_acked = 1;
213 } else {
214 end_seq = TCP_SKB_CB(skb)->seq + 1;
215 }
200 } 216 }
201 tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; 217 tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = end_seq;
202 sk->sk_data_ready(sk); 218 sk->sk_data_ready(sk);
203 bh_unlock_sock(child); 219 bh_unlock_sock(child);
204 sock_put(child); 220 sock_put(child);
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index d10f6f4ead27..4915d8284a86 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -402,6 +402,13 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff)
402 } 402 }
403 403
404 rcu_read_unlock(); 404 rcu_read_unlock();
405
406 if (skb->remcsum_offload)
407 skb_shinfo(skb)->gso_type |= SKB_GSO_TUNNEL_REMCSUM;
408
409 skb->encapsulation = 1;
410 skb_set_inner_mac_header(skb, nhoff + sizeof(struct udphdr));
411
405 return err; 412 return err;
406} 413}
407 414
@@ -410,9 +417,13 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
410 const struct iphdr *iph = ip_hdr(skb); 417 const struct iphdr *iph = ip_hdr(skb);
411 struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); 418 struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
412 419
413 if (uh->check) 420 if (uh->check) {
421 skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM;
414 uh->check = ~udp_v4_check(skb->len - nhoff, iph->saddr, 422 uh->check = ~udp_v4_check(skb->len - nhoff, iph->saddr,
415 iph->daddr, 0); 423 iph->daddr, 0);
424 } else {
425 skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
426 }
416 427
417 return udp_gro_complete(skb, nhoff); 428 return udp_gro_complete(skb, nhoff);
418} 429}