diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 4 | ||||
-rw-r--r-- | net/core/ethtool.c | 6 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 24 | ||||
-rw-r--r-- | net/core/skbuff.c | 36 | ||||
-rw-r--r-- | net/core/tso.c | 3 |
5 files changed, 45 insertions, 28 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index b793e3521a36..945bbd001359 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4157,6 +4157,10 @@ EXPORT_SYMBOL(napi_gro_receive); | |||
4157 | 4157 | ||
4158 | static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) | 4158 | static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) |
4159 | { | 4159 | { |
4160 | if (unlikely(skb->pfmemalloc)) { | ||
4161 | consume_skb(skb); | ||
4162 | return; | ||
4163 | } | ||
4160 | __skb_pull(skb, skb_headlen(skb)); | 4164 | __skb_pull(skb, skb_headlen(skb)); |
4161 | /* restore the reserve we had after netdev_alloc_skb_ip_align() */ | 4165 | /* restore the reserve we had after netdev_alloc_skb_ip_align() */ |
4162 | skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb)); | 4166 | skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb)); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 1600aa24d36b..06dfb293e5aa 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -1036,7 +1036,8 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
1036 | { | 1036 | { |
1037 | const struct ethtool_ops *ops = dev->ethtool_ops; | 1037 | const struct ethtool_ops *ops = dev->ethtool_ops; |
1038 | 1038 | ||
1039 | if (!ops->get_eeprom || !ops->get_eeprom_len) | 1039 | if (!ops->get_eeprom || !ops->get_eeprom_len || |
1040 | !ops->get_eeprom_len(dev)) | ||
1040 | return -EOPNOTSUPP; | 1041 | return -EOPNOTSUPP; |
1041 | 1042 | ||
1042 | return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom, | 1043 | return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom, |
@@ -1052,7 +1053,8 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
1052 | u8 *data; | 1053 | u8 *data; |
1053 | int ret = 0; | 1054 | int ret = 0; |
1054 | 1055 | ||
1055 | if (!ops->set_eeprom || !ops->get_eeprom_len) | 1056 | if (!ops->set_eeprom || !ops->get_eeprom_len || |
1057 | !ops->get_eeprom_len(dev)) | ||
1056 | return -EOPNOTSUPP; | 1058 | return -EOPNOTSUPP; |
1057 | 1059 | ||
1058 | if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) | 1060 | if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a6882686ca3a..76321ea442c3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1498,6 +1498,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1498 | goto errout; | 1498 | goto errout; |
1499 | } | 1499 | } |
1500 | if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { | 1500 | if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { |
1501 | put_net(net); | ||
1501 | err = -EPERM; | 1502 | err = -EPERM; |
1502 | goto errout; | 1503 | goto errout; |
1503 | } | 1504 | } |
@@ -2685,13 +2686,20 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
2685 | int idx = 0; | 2686 | int idx = 0; |
2686 | u32 portid = NETLINK_CB(cb->skb).portid; | 2687 | u32 portid = NETLINK_CB(cb->skb).portid; |
2687 | u32 seq = cb->nlh->nlmsg_seq; | 2688 | u32 seq = cb->nlh->nlmsg_seq; |
2688 | struct nlattr *extfilt; | ||
2689 | u32 filter_mask = 0; | 2689 | u32 filter_mask = 0; |
2690 | 2690 | ||
2691 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), | 2691 | if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { |
2692 | IFLA_EXT_MASK); | 2692 | struct nlattr *extfilt; |
2693 | if (extfilt) | 2693 | |
2694 | filter_mask = nla_get_u32(extfilt); | 2694 | extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), |
2695 | IFLA_EXT_MASK); | ||
2696 | if (extfilt) { | ||
2697 | if (nla_len(extfilt) < sizeof(filter_mask)) | ||
2698 | return -EINVAL; | ||
2699 | |||
2700 | filter_mask = nla_get_u32(extfilt); | ||
2701 | } | ||
2702 | } | ||
2695 | 2703 | ||
2696 | rcu_read_lock(); | 2704 | rcu_read_lock(); |
2697 | for_each_netdev_rcu(net, dev) { | 2705 | for_each_netdev_rcu(net, dev) { |
@@ -2798,6 +2806,9 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2798 | if (br_spec) { | 2806 | if (br_spec) { |
2799 | nla_for_each_nested(attr, br_spec, rem) { | 2807 | nla_for_each_nested(attr, br_spec, rem) { |
2800 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | 2808 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
2809 | if (nla_len(attr) < sizeof(flags)) | ||
2810 | return -EINVAL; | ||
2811 | |||
2801 | have_flags = true; | 2812 | have_flags = true; |
2802 | flags = nla_get_u16(attr); | 2813 | flags = nla_get_u16(attr); |
2803 | break; | 2814 | break; |
@@ -2868,6 +2879,9 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2868 | if (br_spec) { | 2879 | if (br_spec) { |
2869 | nla_for_each_nested(attr, br_spec, rem) { | 2880 | nla_for_each_nested(attr, br_spec, rem) { |
2870 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | 2881 | if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
2882 | if (nla_len(attr) < sizeof(flags)) | ||
2883 | return -EINVAL; | ||
2884 | |||
2871 | have_flags = true; | 2885 | have_flags = true; |
2872 | flags = nla_get_u16(attr); | 2886 | flags = nla_get_u16(attr); |
2873 | break; | 2887 | break; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 61059a05ec95..32e31c299631 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -552,20 +552,13 @@ static void kfree_skbmem(struct sk_buff *skb) | |||
552 | case SKB_FCLONE_CLONE: | 552 | case SKB_FCLONE_CLONE: |
553 | fclones = container_of(skb, struct sk_buff_fclones, skb2); | 553 | fclones = container_of(skb, struct sk_buff_fclones, skb2); |
554 | 554 | ||
555 | /* Warning : We must perform the atomic_dec_and_test() before | 555 | /* The clone portion is available for |
556 | * setting skb->fclone back to SKB_FCLONE_FREE, otherwise | 556 | * fast-cloning again. |
557 | * skb_clone() could set clone_ref to 2 before our decrement. | ||
558 | * Anyway, if we are going to free the structure, no need to | ||
559 | * rewrite skb->fclone. | ||
560 | */ | 557 | */ |
561 | if (atomic_dec_and_test(&fclones->fclone_ref)) { | 558 | skb->fclone = SKB_FCLONE_FREE; |
559 | |||
560 | if (atomic_dec_and_test(&fclones->fclone_ref)) | ||
562 | kmem_cache_free(skbuff_fclone_cache, fclones); | 561 | kmem_cache_free(skbuff_fclone_cache, fclones); |
563 | } else { | ||
564 | /* The clone portion is available for | ||
565 | * fast-cloning again. | ||
566 | */ | ||
567 | skb->fclone = SKB_FCLONE_FREE; | ||
568 | } | ||
569 | break; | 562 | break; |
570 | } | 563 | } |
571 | } | 564 | } |
@@ -887,11 +880,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
887 | if (skb->fclone == SKB_FCLONE_ORIG && | 880 | if (skb->fclone == SKB_FCLONE_ORIG && |
888 | n->fclone == SKB_FCLONE_FREE) { | 881 | n->fclone == SKB_FCLONE_FREE) { |
889 | n->fclone = SKB_FCLONE_CLONE; | 882 | n->fclone = SKB_FCLONE_CLONE; |
890 | /* As our fastclone was free, clone_ref must be 1 at this point. | 883 | atomic_inc(&fclones->fclone_ref); |
891 | * We could use atomic_inc() here, but it is faster | ||
892 | * to set the final value. | ||
893 | */ | ||
894 | atomic_set(&fclones->fclone_ref, 2); | ||
895 | } else { | 884 | } else { |
896 | if (skb_pfmemalloc(skb)) | 885 | if (skb_pfmemalloc(skb)) |
897 | gfp_mask |= __GFP_MEMALLOC; | 886 | gfp_mask |= __GFP_MEMALLOC; |
@@ -4070,15 +4059,22 @@ EXPORT_SYMBOL_GPL(skb_scrub_packet); | |||
4070 | unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) | 4059 | unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) |
4071 | { | 4060 | { |
4072 | const struct skb_shared_info *shinfo = skb_shinfo(skb); | 4061 | const struct skb_shared_info *shinfo = skb_shinfo(skb); |
4062 | unsigned int thlen = 0; | ||
4073 | 4063 | ||
4074 | if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) | 4064 | if (skb->encapsulation) { |
4075 | return tcp_hdrlen(skb) + shinfo->gso_size; | 4065 | thlen = skb_inner_transport_header(skb) - |
4066 | skb_transport_header(skb); | ||
4076 | 4067 | ||
4068 | if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) | ||
4069 | thlen += inner_tcp_hdrlen(skb); | ||
4070 | } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { | ||
4071 | thlen = tcp_hdrlen(skb); | ||
4072 | } | ||
4077 | /* UFO sets gso_size to the size of the fragmentation | 4073 | /* UFO sets gso_size to the size of the fragmentation |
4078 | * payload, i.e. the size of the L4 (UDP) header is already | 4074 | * payload, i.e. the size of the L4 (UDP) header is already |
4079 | * accounted for. | 4075 | * accounted for. |
4080 | */ | 4076 | */ |
4081 | return shinfo->gso_size; | 4077 | return thlen + shinfo->gso_size; |
4082 | } | 4078 | } |
4083 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); | 4079 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); |
4084 | 4080 | ||
diff --git a/net/core/tso.c b/net/core/tso.c index 8c3203c585b0..630b30b4fb53 100644 --- a/net/core/tso.c +++ b/net/core/tso.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/export.h> | 1 | #include <linux/export.h> |
2 | #include <net/ip.h> | 2 | #include <net/ip.h> |
3 | #include <net/tso.h> | 3 | #include <net/tso.h> |
4 | #include <asm/unaligned.h> | ||
4 | 5 | ||
5 | /* Calculate expected number of TX descriptors */ | 6 | /* Calculate expected number of TX descriptors */ |
6 | int tso_count_descs(struct sk_buff *skb) | 7 | int tso_count_descs(struct sk_buff *skb) |
@@ -23,7 +24,7 @@ void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, | |||
23 | iph->id = htons(tso->ip_id); | 24 | iph->id = htons(tso->ip_id); |
24 | iph->tot_len = htons(size + hdr_len - mac_hdr_len); | 25 | iph->tot_len = htons(size + hdr_len - mac_hdr_len); |
25 | tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb)); | 26 | tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb)); |
26 | tcph->seq = htonl(tso->tcp_seq); | 27 | put_unaligned_be32(tso->tcp_seq, &tcph->seq); |
27 | tso->ip_id++; | 28 | tso->ip_id++; |
28 | 29 | ||
29 | if (!is_last) { | 30 | if (!is_last) { |