diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 59 | ||||
-rw-r--r-- | net/core/neighbour.c | 6 | ||||
-rw-r--r-- | net/core/netprio_cgroup.c | 38 | ||||
-rw-r--r-- | net/core/pktgen.c | 146 | ||||
-rw-r--r-- | net/core/scm.c | 3 | ||||
-rw-r--r-- | net/core/skbuff.c | 47 | ||||
-rw-r--r-- | net/core/utils.c | 24 |
7 files changed, 112 insertions, 211 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 1e0a1847c3bb..09cb3f6dc40c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3300,18 +3300,18 @@ ncls: | |||
3300 | && !skb_pfmemalloc_protocol(skb)) | 3300 | && !skb_pfmemalloc_protocol(skb)) |
3301 | goto drop; | 3301 | goto drop; |
3302 | 3302 | ||
3303 | rx_handler = rcu_dereference(skb->dev->rx_handler); | ||
3304 | if (vlan_tx_tag_present(skb)) { | 3303 | if (vlan_tx_tag_present(skb)) { |
3305 | if (pt_prev) { | 3304 | if (pt_prev) { |
3306 | ret = deliver_skb(skb, pt_prev, orig_dev); | 3305 | ret = deliver_skb(skb, pt_prev, orig_dev); |
3307 | pt_prev = NULL; | 3306 | pt_prev = NULL; |
3308 | } | 3307 | } |
3309 | if (vlan_do_receive(&skb, !rx_handler)) | 3308 | if (vlan_do_receive(&skb)) |
3310 | goto another_round; | 3309 | goto another_round; |
3311 | else if (unlikely(!skb)) | 3310 | else if (unlikely(!skb)) |
3312 | goto unlock; | 3311 | goto unlock; |
3313 | } | 3312 | } |
3314 | 3313 | ||
3314 | rx_handler = rcu_dereference(skb->dev->rx_handler); | ||
3315 | if (rx_handler) { | 3315 | if (rx_handler) { |
3316 | if (pt_prev) { | 3316 | if (pt_prev) { |
3317 | ret = deliver_skb(skb, pt_prev, orig_dev); | 3317 | ret = deliver_skb(skb, pt_prev, orig_dev); |
@@ -3331,6 +3331,9 @@ ncls: | |||
3331 | } | 3331 | } |
3332 | } | 3332 | } |
3333 | 3333 | ||
3334 | if (vlan_tx_nonzero_tag_present(skb)) | ||
3335 | skb->pkt_type = PACKET_OTHERHOST; | ||
3336 | |||
3334 | /* deliver only exact match when indicated */ | 3337 | /* deliver only exact match when indicated */ |
3335 | null_or_dev = deliver_exact ? skb->dev : NULL; | 3338 | null_or_dev = deliver_exact ? skb->dev : NULL; |
3336 | 3339 | ||
@@ -3471,17 +3474,31 @@ out: | |||
3471 | return netif_receive_skb(skb); | 3474 | return netif_receive_skb(skb); |
3472 | } | 3475 | } |
3473 | 3476 | ||
3474 | inline void napi_gro_flush(struct napi_struct *napi) | 3477 | /* napi->gro_list contains packets ordered by age. |
3478 | * youngest packets at the head of it. | ||
3479 | * Complete skbs in reverse order to reduce latencies. | ||
3480 | */ | ||
3481 | void napi_gro_flush(struct napi_struct *napi, bool flush_old) | ||
3475 | { | 3482 | { |
3476 | struct sk_buff *skb, *next; | 3483 | struct sk_buff *skb, *prev = NULL; |
3477 | 3484 | ||
3478 | for (skb = napi->gro_list; skb; skb = next) { | 3485 | /* scan list and build reverse chain */ |
3479 | next = skb->next; | 3486 | for (skb = napi->gro_list; skb != NULL; skb = skb->next) { |
3487 | skb->prev = prev; | ||
3488 | prev = skb; | ||
3489 | } | ||
3490 | |||
3491 | for (skb = prev; skb; skb = prev) { | ||
3480 | skb->next = NULL; | 3492 | skb->next = NULL; |
3493 | |||
3494 | if (flush_old && NAPI_GRO_CB(skb)->age == jiffies) | ||
3495 | return; | ||
3496 | |||
3497 | prev = skb->prev; | ||
3481 | napi_gro_complete(skb); | 3498 | napi_gro_complete(skb); |
3499 | napi->gro_count--; | ||
3482 | } | 3500 | } |
3483 | 3501 | ||
3484 | napi->gro_count = 0; | ||
3485 | napi->gro_list = NULL; | 3502 | napi->gro_list = NULL; |
3486 | } | 3503 | } |
3487 | EXPORT_SYMBOL(napi_gro_flush); | 3504 | EXPORT_SYMBOL(napi_gro_flush); |
@@ -3542,6 +3559,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
3542 | 3559 | ||
3543 | napi->gro_count++; | 3560 | napi->gro_count++; |
3544 | NAPI_GRO_CB(skb)->count = 1; | 3561 | NAPI_GRO_CB(skb)->count = 1; |
3562 | NAPI_GRO_CB(skb)->age = jiffies; | ||
3545 | skb_shinfo(skb)->gso_size = skb_gro_len(skb); | 3563 | skb_shinfo(skb)->gso_size = skb_gro_len(skb); |
3546 | skb->next = napi->gro_list; | 3564 | skb->next = napi->gro_list; |
3547 | napi->gro_list = skb; | 3565 | napi->gro_list = skb; |
@@ -3631,20 +3649,22 @@ gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) | |||
3631 | } | 3649 | } |
3632 | EXPORT_SYMBOL(napi_skb_finish); | 3650 | EXPORT_SYMBOL(napi_skb_finish); |
3633 | 3651 | ||
3634 | void skb_gro_reset_offset(struct sk_buff *skb) | 3652 | static void skb_gro_reset_offset(struct sk_buff *skb) |
3635 | { | 3653 | { |
3654 | const struct skb_shared_info *pinfo = skb_shinfo(skb); | ||
3655 | const skb_frag_t *frag0 = &pinfo->frags[0]; | ||
3656 | |||
3636 | NAPI_GRO_CB(skb)->data_offset = 0; | 3657 | NAPI_GRO_CB(skb)->data_offset = 0; |
3637 | NAPI_GRO_CB(skb)->frag0 = NULL; | 3658 | NAPI_GRO_CB(skb)->frag0 = NULL; |
3638 | NAPI_GRO_CB(skb)->frag0_len = 0; | 3659 | NAPI_GRO_CB(skb)->frag0_len = 0; |
3639 | 3660 | ||
3640 | if (skb->mac_header == skb->tail && | 3661 | if (skb->mac_header == skb->tail && |
3641 | !PageHighMem(skb_frag_page(&skb_shinfo(skb)->frags[0]))) { | 3662 | pinfo->nr_frags && |
3642 | NAPI_GRO_CB(skb)->frag0 = | 3663 | !PageHighMem(skb_frag_page(frag0))) { |
3643 | skb_frag_address(&skb_shinfo(skb)->frags[0]); | 3664 | NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0); |
3644 | NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(&skb_shinfo(skb)->frags[0]); | 3665 | NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0); |
3645 | } | 3666 | } |
3646 | } | 3667 | } |
3647 | EXPORT_SYMBOL(skb_gro_reset_offset); | ||
3648 | 3668 | ||
3649 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 3669 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
3650 | { | 3670 | { |
@@ -3876,7 +3896,7 @@ void napi_complete(struct napi_struct *n) | |||
3876 | if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state))) | 3896 | if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state))) |
3877 | return; | 3897 | return; |
3878 | 3898 | ||
3879 | napi_gro_flush(n); | 3899 | napi_gro_flush(n, false); |
3880 | local_irq_save(flags); | 3900 | local_irq_save(flags); |
3881 | __napi_complete(n); | 3901 | __napi_complete(n); |
3882 | local_irq_restore(flags); | 3902 | local_irq_restore(flags); |
@@ -3981,8 +4001,17 @@ static void net_rx_action(struct softirq_action *h) | |||
3981 | local_irq_enable(); | 4001 | local_irq_enable(); |
3982 | napi_complete(n); | 4002 | napi_complete(n); |
3983 | local_irq_disable(); | 4003 | local_irq_disable(); |
3984 | } else | 4004 | } else { |
4005 | if (n->gro_list) { | ||
4006 | /* flush too old packets | ||
4007 | * If HZ < 1000, flush all packets. | ||
4008 | */ | ||
4009 | local_irq_enable(); | ||
4010 | napi_gro_flush(n, HZ >= 1000); | ||
4011 | local_irq_disable(); | ||
4012 | } | ||
3985 | list_move_tail(&n->poll_list, &sd->poll_list); | 4013 | list_move_tail(&n->poll_list, &sd->poll_list); |
4014 | } | ||
3986 | } | 4015 | } |
3987 | 4016 | ||
3988 | netpoll_poll_unlock(have); | 4017 | netpoll_poll_unlock(have); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index baca771caae2..22571488730a 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -1301,8 +1301,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) | |||
1301 | if (!dst) | 1301 | if (!dst) |
1302 | goto discard; | 1302 | goto discard; |
1303 | 1303 | ||
1304 | __skb_pull(skb, skb_network_offset(skb)); | ||
1305 | |||
1306 | if (!neigh_event_send(neigh, skb)) { | 1304 | if (!neigh_event_send(neigh, skb)) { |
1307 | int err; | 1305 | int err; |
1308 | struct net_device *dev = neigh->dev; | 1306 | struct net_device *dev = neigh->dev; |
@@ -1312,6 +1310,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) | |||
1312 | neigh_hh_init(neigh, dst); | 1310 | neigh_hh_init(neigh, dst); |
1313 | 1311 | ||
1314 | do { | 1312 | do { |
1313 | __skb_pull(skb, skb_network_offset(skb)); | ||
1315 | seq = read_seqbegin(&neigh->ha_lock); | 1314 | seq = read_seqbegin(&neigh->ha_lock); |
1316 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1315 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), |
1317 | neigh->ha, NULL, skb->len); | 1316 | neigh->ha, NULL, skb->len); |
@@ -1342,9 +1341,8 @@ int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) | |||
1342 | unsigned int seq; | 1341 | unsigned int seq; |
1343 | int err; | 1342 | int err; |
1344 | 1343 | ||
1345 | __skb_pull(skb, skb_network_offset(skb)); | ||
1346 | |||
1347 | do { | 1344 | do { |
1345 | __skb_pull(skb, skb_network_offset(skb)); | ||
1348 | seq = read_seqbegin(&neigh->ha_lock); | 1346 | seq = read_seqbegin(&neigh->ha_lock); |
1349 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1347 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), |
1350 | neigh->ha, NULL, skb->len); | 1348 | neigh->ha, NULL, skb->len); |
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 4a83fb3c8e87..79285a36035f 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c | |||
@@ -239,38 +239,24 @@ out_free_devname: | |||
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
241 | 241 | ||
242 | static int update_netprio(const void *v, struct file *file, unsigned n) | ||
243 | { | ||
244 | int err; | ||
245 | struct socket *sock = sock_from_file(file, &err); | ||
246 | if (sock) | ||
247 | sock->sk->sk_cgrp_prioidx = (u32)(unsigned long)v; | ||
248 | return 0; | ||
249 | } | ||
250 | |||
242 | void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) | 251 | void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) |
243 | { | 252 | { |
244 | struct task_struct *p; | 253 | struct task_struct *p; |
254 | void *v; | ||
245 | 255 | ||
246 | cgroup_taskset_for_each(p, cgrp, tset) { | 256 | cgroup_taskset_for_each(p, cgrp, tset) { |
247 | unsigned int fd; | ||
248 | struct fdtable *fdt; | ||
249 | struct files_struct *files; | ||
250 | |||
251 | task_lock(p); | 257 | task_lock(p); |
252 | files = p->files; | 258 | v = (void *)(unsigned long)task_netprioidx(p); |
253 | if (!files) { | 259 | iterate_fd(p->files, 0, update_netprio, v); |
254 | task_unlock(p); | ||
255 | continue; | ||
256 | } | ||
257 | |||
258 | spin_lock(&files->file_lock); | ||
259 | fdt = files_fdtable(files); | ||
260 | for (fd = 0; fd < fdt->max_fds; fd++) { | ||
261 | struct file *file; | ||
262 | struct socket *sock; | ||
263 | int err; | ||
264 | |||
265 | file = fcheck_files(files, fd); | ||
266 | if (!file) | ||
267 | continue; | ||
268 | |||
269 | sock = sock_from_file(file, &err); | ||
270 | if (sock) | ||
271 | sock_update_netprioidx(sock->sk, p); | ||
272 | } | ||
273 | spin_unlock(&files->file_lock); | ||
274 | task_unlock(p); | 260 | task_unlock(p); |
275 | } | 261 | } |
276 | } | 262 | } |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 148e73d2c451..d1dc14c2aac4 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -248,8 +248,8 @@ struct pktgen_dev { | |||
248 | int removal_mark; /* non-zero => the device is marked for | 248 | int removal_mark; /* non-zero => the device is marked for |
249 | * removal by worker thread */ | 249 | * removal by worker thread */ |
250 | 250 | ||
251 | int min_pkt_size; /* = ETH_ZLEN; */ | 251 | int min_pkt_size; |
252 | int max_pkt_size; /* = ETH_ZLEN; */ | 252 | int max_pkt_size; |
253 | int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */ | 253 | int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */ |
254 | int nfrags; | 254 | int nfrags; |
255 | struct page *page; | 255 | struct page *page; |
@@ -449,8 +449,6 @@ static void pktgen_stop_all_threads_ifs(void); | |||
449 | static void pktgen_stop(struct pktgen_thread *t); | 449 | static void pktgen_stop(struct pktgen_thread *t); |
450 | static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); | 450 | static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); |
451 | 451 | ||
452 | static unsigned int scan_ip6(const char *s, char ip[16]); | ||
453 | |||
454 | /* Module parameters, defaults. */ | 452 | /* Module parameters, defaults. */ |
455 | static int pg_count_d __read_mostly = 1000; | 453 | static int pg_count_d __read_mostly = 1000; |
456 | static int pg_delay_d __read_mostly; | 454 | static int pg_delay_d __read_mostly; |
@@ -702,8 +700,8 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
702 | &pkt_dev->cur_in6_saddr, | 700 | &pkt_dev->cur_in6_saddr, |
703 | &pkt_dev->cur_in6_daddr); | 701 | &pkt_dev->cur_in6_daddr); |
704 | } else | 702 | } else |
705 | seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", | 703 | seq_printf(seq, " cur_saddr: %pI4 cur_daddr: %pI4\n", |
706 | pkt_dev->cur_saddr, pkt_dev->cur_daddr); | 704 | &pkt_dev->cur_saddr, &pkt_dev->cur_daddr); |
707 | 705 | ||
708 | seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n", | 706 | seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n", |
709 | pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src); | 707 | pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src); |
@@ -1299,7 +1297,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1299 | return -EFAULT; | 1297 | return -EFAULT; |
1300 | buf[len] = 0; | 1298 | buf[len] = 0; |
1301 | 1299 | ||
1302 | scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); | 1300 | in6_pton(buf, -1, pkt_dev->in6_daddr.s6_addr, -1, NULL); |
1303 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr); | 1301 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr); |
1304 | 1302 | ||
1305 | pkt_dev->cur_in6_daddr = pkt_dev->in6_daddr; | 1303 | pkt_dev->cur_in6_daddr = pkt_dev->in6_daddr; |
@@ -1322,7 +1320,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1322 | return -EFAULT; | 1320 | return -EFAULT; |
1323 | buf[len] = 0; | 1321 | buf[len] = 0; |
1324 | 1322 | ||
1325 | scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); | 1323 | in6_pton(buf, -1, pkt_dev->min_in6_daddr.s6_addr, -1, NULL); |
1326 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr); | 1324 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr); |
1327 | 1325 | ||
1328 | pkt_dev->cur_in6_daddr = pkt_dev->min_in6_daddr; | 1326 | pkt_dev->cur_in6_daddr = pkt_dev->min_in6_daddr; |
@@ -1344,7 +1342,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1344 | return -EFAULT; | 1342 | return -EFAULT; |
1345 | buf[len] = 0; | 1343 | buf[len] = 0; |
1346 | 1344 | ||
1347 | scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); | 1345 | in6_pton(buf, -1, pkt_dev->max_in6_daddr.s6_addr, -1, NULL); |
1348 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr); | 1346 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr); |
1349 | 1347 | ||
1350 | if (debug) | 1348 | if (debug) |
@@ -1365,7 +1363,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1365 | return -EFAULT; | 1363 | return -EFAULT; |
1366 | buf[len] = 0; | 1364 | buf[len] = 0; |
1367 | 1365 | ||
1368 | scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); | 1366 | in6_pton(buf, -1, pkt_dev->in6_saddr.s6_addr, -1, NULL); |
1369 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr); | 1367 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr); |
1370 | 1368 | ||
1371 | pkt_dev->cur_in6_saddr = pkt_dev->in6_saddr; | 1369 | pkt_dev->cur_in6_saddr = pkt_dev->in6_saddr; |
@@ -2036,19 +2034,17 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
2036 | /* Set up Dest MAC */ | 2034 | /* Set up Dest MAC */ |
2037 | memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); | 2035 | memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); |
2038 | 2036 | ||
2039 | /* Set up pkt size */ | ||
2040 | pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; | ||
2041 | |||
2042 | if (pkt_dev->flags & F_IPV6) { | 2037 | if (pkt_dev->flags & F_IPV6) { |
2043 | /* | ||
2044 | * Skip this automatic address setting until locks or functions | ||
2045 | * gets exported | ||
2046 | */ | ||
2047 | |||
2048 | #ifdef NOTNOW | ||
2049 | int i, set = 0, err = 1; | 2038 | int i, set = 0, err = 1; |
2050 | struct inet6_dev *idev; | 2039 | struct inet6_dev *idev; |
2051 | 2040 | ||
2041 | if (pkt_dev->min_pkt_size == 0) { | ||
2042 | pkt_dev->min_pkt_size = 14 + sizeof(struct ipv6hdr) | ||
2043 | + sizeof(struct udphdr) | ||
2044 | + sizeof(struct pktgen_hdr) | ||
2045 | + pkt_dev->pkt_overhead; | ||
2046 | } | ||
2047 | |||
2052 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | 2048 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
2053 | if (pkt_dev->cur_in6_saddr.s6_addr[i]) { | 2049 | if (pkt_dev->cur_in6_saddr.s6_addr[i]) { |
2054 | set = 1; | 2050 | set = 1; |
@@ -2069,9 +2065,8 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
2069 | struct inet6_ifaddr *ifp; | 2065 | struct inet6_ifaddr *ifp; |
2070 | 2066 | ||
2071 | read_lock_bh(&idev->lock); | 2067 | read_lock_bh(&idev->lock); |
2072 | for (ifp = idev->addr_list; ifp; | 2068 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2073 | ifp = ifp->if_next) { | 2069 | if ((ifp->scope & IFA_LINK) && |
2074 | if (ifp->scope == IFA_LINK && | ||
2075 | !(ifp->flags & IFA_F_TENTATIVE)) { | 2070 | !(ifp->flags & IFA_F_TENTATIVE)) { |
2076 | pkt_dev->cur_in6_saddr = ifp->addr; | 2071 | pkt_dev->cur_in6_saddr = ifp->addr; |
2077 | err = 0; | 2072 | err = 0; |
@@ -2084,8 +2079,14 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
2084 | if (err) | 2079 | if (err) |
2085 | pr_err("ERROR: IPv6 link address not available\n"); | 2080 | pr_err("ERROR: IPv6 link address not available\n"); |
2086 | } | 2081 | } |
2087 | #endif | ||
2088 | } else { | 2082 | } else { |
2083 | if (pkt_dev->min_pkt_size == 0) { | ||
2084 | pkt_dev->min_pkt_size = 14 + sizeof(struct iphdr) | ||
2085 | + sizeof(struct udphdr) | ||
2086 | + sizeof(struct pktgen_hdr) | ||
2087 | + pkt_dev->pkt_overhead; | ||
2088 | } | ||
2089 | |||
2089 | pkt_dev->saddr_min = 0; | 2090 | pkt_dev->saddr_min = 0; |
2090 | pkt_dev->saddr_max = 0; | 2091 | pkt_dev->saddr_max = 0; |
2091 | if (strlen(pkt_dev->src_min) == 0) { | 2092 | if (strlen(pkt_dev->src_min) == 0) { |
@@ -2111,6 +2112,10 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
2111 | pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); | 2112 | pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); |
2112 | } | 2113 | } |
2113 | /* Initialize current values. */ | 2114 | /* Initialize current values. */ |
2115 | pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; | ||
2116 | if (pkt_dev->min_pkt_size > pkt_dev->max_pkt_size) | ||
2117 | pkt_dev->max_pkt_size = pkt_dev->min_pkt_size; | ||
2118 | |||
2114 | pkt_dev->cur_dst_mac_offset = 0; | 2119 | pkt_dev->cur_dst_mac_offset = 0; |
2115 | pkt_dev->cur_src_mac_offset = 0; | 2120 | pkt_dev->cur_src_mac_offset = 0; |
2116 | pkt_dev->cur_saddr = pkt_dev->saddr_min; | 2121 | pkt_dev->cur_saddr = pkt_dev->saddr_min; |
@@ -2758,97 +2763,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2758 | return skb; | 2763 | return skb; |
2759 | } | 2764 | } |
2760 | 2765 | ||
2761 | /* | ||
2762 | * scan_ip6, fmt_ip taken from dietlibc-0.21 | ||
2763 | * Author Felix von Leitner <felix-dietlibc@fefe.de> | ||
2764 | * | ||
2765 | * Slightly modified for kernel. | ||
2766 | * Should be candidate for net/ipv4/utils.c | ||
2767 | * --ro | ||
2768 | */ | ||
2769 | |||
2770 | static unsigned int scan_ip6(const char *s, char ip[16]) | ||
2771 | { | ||
2772 | unsigned int i; | ||
2773 | unsigned int len = 0; | ||
2774 | unsigned long u; | ||
2775 | char suffix[16]; | ||
2776 | unsigned int prefixlen = 0; | ||
2777 | unsigned int suffixlen = 0; | ||
2778 | __be32 tmp; | ||
2779 | char *pos; | ||
2780 | |||
2781 | for (i = 0; i < 16; i++) | ||
2782 | ip[i] = 0; | ||
2783 | |||
2784 | for (;;) { | ||
2785 | if (*s == ':') { | ||
2786 | len++; | ||
2787 | if (s[1] == ':') { /* Found "::", skip to part 2 */ | ||
2788 | s += 2; | ||
2789 | len++; | ||
2790 | break; | ||
2791 | } | ||
2792 | s++; | ||
2793 | } | ||
2794 | |||
2795 | u = simple_strtoul(s, &pos, 16); | ||
2796 | i = pos - s; | ||
2797 | if (!i) | ||
2798 | return 0; | ||
2799 | if (prefixlen == 12 && s[i] == '.') { | ||
2800 | |||
2801 | /* the last 4 bytes may be written as IPv4 address */ | ||
2802 | |||
2803 | tmp = in_aton(s); | ||
2804 | memcpy((struct in_addr *)(ip + 12), &tmp, sizeof(tmp)); | ||
2805 | return i + len; | ||
2806 | } | ||
2807 | ip[prefixlen++] = (u >> 8); | ||
2808 | ip[prefixlen++] = (u & 255); | ||
2809 | s += i; | ||
2810 | len += i; | ||
2811 | if (prefixlen == 16) | ||
2812 | return len; | ||
2813 | } | ||
2814 | |||
2815 | /* part 2, after "::" */ | ||
2816 | for (;;) { | ||
2817 | if (*s == ':') { | ||
2818 | if (suffixlen == 0) | ||
2819 | break; | ||
2820 | s++; | ||
2821 | len++; | ||
2822 | } else if (suffixlen != 0) | ||
2823 | break; | ||
2824 | |||
2825 | u = simple_strtol(s, &pos, 16); | ||
2826 | i = pos - s; | ||
2827 | if (!i) { | ||
2828 | if (*s) | ||
2829 | len--; | ||
2830 | break; | ||
2831 | } | ||
2832 | if (suffixlen + prefixlen <= 12 && s[i] == '.') { | ||
2833 | tmp = in_aton(s); | ||
2834 | memcpy((struct in_addr *)(suffix + suffixlen), &tmp, | ||
2835 | sizeof(tmp)); | ||
2836 | suffixlen += 4; | ||
2837 | len += strlen(s); | ||
2838 | break; | ||
2839 | } | ||
2840 | suffix[suffixlen++] = (u >> 8); | ||
2841 | suffix[suffixlen++] = (u & 255); | ||
2842 | s += i; | ||
2843 | len += i; | ||
2844 | if (prefixlen + suffixlen == 16) | ||
2845 | break; | ||
2846 | } | ||
2847 | for (i = 0; i < suffixlen; i++) | ||
2848 | ip[16 - suffixlen + i] = suffix[i]; | ||
2849 | return len; | ||
2850 | } | ||
2851 | |||
2852 | static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | 2766 | static struct sk_buff *fill_packet_ipv6(struct net_device *odev, |
2853 | struct pktgen_dev *pkt_dev) | 2767 | struct pktgen_dev *pkt_dev) |
2854 | { | 2768 | { |
@@ -2927,7 +2841,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | |||
2927 | sizeof(struct ipv6hdr) - sizeof(struct udphdr) - | 2841 | sizeof(struct ipv6hdr) - sizeof(struct udphdr) - |
2928 | pkt_dev->pkt_overhead; | 2842 | pkt_dev->pkt_overhead; |
2929 | 2843 | ||
2930 | if (datalen < sizeof(struct pktgen_hdr)) { | 2844 | if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) { |
2931 | datalen = sizeof(struct pktgen_hdr); | 2845 | datalen = sizeof(struct pktgen_hdr); |
2932 | net_info_ratelimited("increased datalen to %d\n", datalen); | 2846 | net_info_ratelimited("increased datalen to %d\n", datalen); |
2933 | } | 2847 | } |
@@ -3548,8 +3462,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
3548 | } | 3462 | } |
3549 | 3463 | ||
3550 | pkt_dev->removal_mark = 0; | 3464 | pkt_dev->removal_mark = 0; |
3551 | pkt_dev->min_pkt_size = ETH_ZLEN; | ||
3552 | pkt_dev->max_pkt_size = ETH_ZLEN; | ||
3553 | pkt_dev->nfrags = 0; | 3465 | pkt_dev->nfrags = 0; |
3554 | pkt_dev->delay = pg_delay_d; | 3466 | pkt_dev->delay = pg_delay_d; |
3555 | pkt_dev->count = pg_count_d; | 3467 | pkt_dev->count = pg_count_d; |
diff --git a/net/core/scm.c b/net/core/scm.c index 9c1c63da3ca8..ab570841a532 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -301,11 +301,10 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
301 | break; | 301 | break; |
302 | } | 302 | } |
303 | /* Bump the usage count and install the file. */ | 303 | /* Bump the usage count and install the file. */ |
304 | get_file(fp[i]); | ||
305 | sock = sock_from_file(fp[i], &err); | 304 | sock = sock_from_file(fp[i], &err); |
306 | if (sock) | 305 | if (sock) |
307 | sock_update_netprioidx(sock->sk, current); | 306 | sock_update_netprioidx(sock->sk, current); |
308 | fd_install(new_fd, fp[i]); | 307 | fd_install(new_fd, get_file(fp[i])); |
309 | } | 308 | } |
310 | 309 | ||
311 | if (i > 0) | 310 | if (i > 0) |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cdc28598f4ef..6e04b1fa11f2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -655,53 +655,6 @@ void consume_skb(struct sk_buff *skb) | |||
655 | } | 655 | } |
656 | EXPORT_SYMBOL(consume_skb); | 656 | EXPORT_SYMBOL(consume_skb); |
657 | 657 | ||
658 | /** | ||
659 | * skb_recycle - clean up an skb for reuse | ||
660 | * @skb: buffer | ||
661 | * | ||
662 | * Recycles the skb to be reused as a receive buffer. This | ||
663 | * function does any necessary reference count dropping, and | ||
664 | * cleans up the skbuff as if it just came from __alloc_skb(). | ||
665 | */ | ||
666 | void skb_recycle(struct sk_buff *skb) | ||
667 | { | ||
668 | struct skb_shared_info *shinfo; | ||
669 | |||
670 | skb_release_head_state(skb); | ||
671 | |||
672 | shinfo = skb_shinfo(skb); | ||
673 | memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); | ||
674 | atomic_set(&shinfo->dataref, 1); | ||
675 | |||
676 | memset(skb, 0, offsetof(struct sk_buff, tail)); | ||
677 | skb->data = skb->head + NET_SKB_PAD; | ||
678 | skb_reset_tail_pointer(skb); | ||
679 | } | ||
680 | EXPORT_SYMBOL(skb_recycle); | ||
681 | |||
682 | /** | ||
683 | * skb_recycle_check - check if skb can be reused for receive | ||
684 | * @skb: buffer | ||
685 | * @skb_size: minimum receive buffer size | ||
686 | * | ||
687 | * Checks that the skb passed in is not shared or cloned, and | ||
688 | * that it is linear and its head portion at least as large as | ||
689 | * skb_size so that it can be recycled as a receive buffer. | ||
690 | * If these conditions are met, this function does any necessary | ||
691 | * reference count dropping and cleans up the skbuff as if it | ||
692 | * just came from __alloc_skb(). | ||
693 | */ | ||
694 | bool skb_recycle_check(struct sk_buff *skb, int skb_size) | ||
695 | { | ||
696 | if (!skb_is_recycleable(skb, skb_size)) | ||
697 | return false; | ||
698 | |||
699 | skb_recycle(skb); | ||
700 | |||
701 | return true; | ||
702 | } | ||
703 | EXPORT_SYMBOL(skb_recycle_check); | ||
704 | |||
705 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | 658 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) |
706 | { | 659 | { |
707 | new->tstamp = old->tstamp; | 660 | new->tstamp = old->tstamp; |
diff --git a/net/core/utils.c b/net/core/utils.c index f5613d569c23..e3487e461939 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -107,6 +107,18 @@ static inline int xdigit2bin(char c, int delim) | |||
107 | return IN6PTON_UNKNOWN; | 107 | return IN6PTON_UNKNOWN; |
108 | } | 108 | } |
109 | 109 | ||
110 | /** | ||
111 | * in4_pton - convert an IPv4 address from literal to binary representation | ||
112 | * @src: the start of the IPv4 address string | ||
113 | * @srclen: the length of the string, -1 means strlen(src) | ||
114 | * @dst: the binary (u8[4] array) representation of the IPv4 address | ||
115 | * @delim: the delimiter of the IPv4 address in @src, -1 means no delimiter | ||
116 | * @end: A pointer to the end of the parsed string will be placed here | ||
117 | * | ||
118 | * Return one on success, return zero when any error occurs | ||
119 | * and @end will point to the end of the parsed string. | ||
120 | * | ||
121 | */ | ||
110 | int in4_pton(const char *src, int srclen, | 122 | int in4_pton(const char *src, int srclen, |
111 | u8 *dst, | 123 | u8 *dst, |
112 | int delim, const char **end) | 124 | int delim, const char **end) |
@@ -161,6 +173,18 @@ out: | |||
161 | } | 173 | } |
162 | EXPORT_SYMBOL(in4_pton); | 174 | EXPORT_SYMBOL(in4_pton); |
163 | 175 | ||
176 | /** | ||
177 | * in6_pton - convert an IPv6 address from literal to binary representation | ||
178 | * @src: the start of the IPv6 address string | ||
179 | * @srclen: the length of the string, -1 means strlen(src) | ||
180 | * @dst: the binary (u8[16] array) representation of the IPv6 address | ||
181 | * @delim: the delimiter of the IPv6 address in @src, -1 means no delimiter | ||
182 | * @end: A pointer to the end of the parsed string will be placed here | ||
183 | * | ||
184 | * Return one on success, return zero when any error occurs | ||
185 | * and @end will point to the end of the parsed string. | ||
186 | * | ||
187 | */ | ||
164 | int in6_pton(const char *src, int srclen, | 188 | int in6_pton(const char *src, int srclen, |
165 | u8 *dst, | 189 | u8 *dst, |
166 | int delim, const char **end) | 190 | int delim, const char **end) |