diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 17 | ||||
| -rw-r--r-- | net/core/netpoll.c | 2 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 10 | ||||
| -rw-r--r-- | net/core/skbuff.c | 30 |
4 files changed, 40 insertions, 19 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index b1b0c8d4d7df..bc3c89792b0c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2286,7 +2286,7 @@ out: | |||
| 2286 | } | 2286 | } |
| 2287 | EXPORT_SYMBOL(skb_checksum_help); | 2287 | EXPORT_SYMBOL(skb_checksum_help); |
| 2288 | 2288 | ||
| 2289 | __be16 skb_network_protocol(struct sk_buff *skb) | 2289 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
| 2290 | { | 2290 | { |
| 2291 | __be16 type = skb->protocol; | 2291 | __be16 type = skb->protocol; |
| 2292 | int vlan_depth = ETH_HLEN; | 2292 | int vlan_depth = ETH_HLEN; |
| @@ -2313,6 +2313,8 @@ __be16 skb_network_protocol(struct sk_buff *skb) | |||
| 2313 | vlan_depth += VLAN_HLEN; | 2313 | vlan_depth += VLAN_HLEN; |
| 2314 | } | 2314 | } |
| 2315 | 2315 | ||
| 2316 | *depth = vlan_depth; | ||
| 2317 | |||
| 2316 | return type; | 2318 | return type; |
| 2317 | } | 2319 | } |
| 2318 | 2320 | ||
| @@ -2326,12 +2328,13 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb, | |||
| 2326 | { | 2328 | { |
| 2327 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); | 2329 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); |
| 2328 | struct packet_offload *ptype; | 2330 | struct packet_offload *ptype; |
| 2329 | __be16 type = skb_network_protocol(skb); | 2331 | int vlan_depth = skb->mac_len; |
| 2332 | __be16 type = skb_network_protocol(skb, &vlan_depth); | ||
| 2330 | 2333 | ||
| 2331 | if (unlikely(!type)) | 2334 | if (unlikely(!type)) |
| 2332 | return ERR_PTR(-EINVAL); | 2335 | return ERR_PTR(-EINVAL); |
| 2333 | 2336 | ||
| 2334 | __skb_pull(skb, skb->mac_len); | 2337 | __skb_pull(skb, vlan_depth); |
| 2335 | 2338 | ||
| 2336 | rcu_read_lock(); | 2339 | rcu_read_lock(); |
| 2337 | list_for_each_entry_rcu(ptype, &offload_base, list) { | 2340 | list_for_each_entry_rcu(ptype, &offload_base, list) { |
| @@ -2498,8 +2501,10 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
| 2498 | const struct net_device *dev, | 2501 | const struct net_device *dev, |
| 2499 | netdev_features_t features) | 2502 | netdev_features_t features) |
| 2500 | { | 2503 | { |
| 2504 | int tmp; | ||
| 2505 | |||
| 2501 | if (skb->ip_summed != CHECKSUM_NONE && | 2506 | if (skb->ip_summed != CHECKSUM_NONE && |
| 2502 | !can_checksum_protocol(features, skb_network_protocol(skb))) { | 2507 | !can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) { |
| 2503 | features &= ~NETIF_F_ALL_CSUM; | 2508 | features &= ~NETIF_F_ALL_CSUM; |
| 2504 | } else if (illegal_highdma(dev, skb)) { | 2509 | } else if (illegal_highdma(dev, skb)) { |
| 2505 | features &= ~NETIF_F_SG; | 2510 | features &= ~NETIF_F_SG; |
| @@ -4130,8 +4135,8 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) | |||
| 4130 | struct softnet_data *next = remsd->rps_ipi_next; | 4135 | struct softnet_data *next = remsd->rps_ipi_next; |
| 4131 | 4136 | ||
| 4132 | if (cpu_online(remsd->cpu)) | 4137 | if (cpu_online(remsd->cpu)) |
| 4133 | __smp_call_function_single(remsd->cpu, | 4138 | smp_call_function_single_async(remsd->cpu, |
| 4134 | &remsd->csd, 0); | 4139 | &remsd->csd); |
| 4135 | remsd = next; | 4140 | remsd = next; |
| 4136 | } | 4141 | } |
| 4137 | } else | 4142 | } else |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a664f7829a6d..df9e6b1a9759 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -742,7 +742,7 @@ static bool pkt_is_ns(struct sk_buff *skb) | |||
| 742 | struct nd_msg *msg; | 742 | struct nd_msg *msg; |
| 743 | struct ipv6hdr *hdr; | 743 | struct ipv6hdr *hdr; |
| 744 | 744 | ||
| 745 | if (skb->protocol != htons(ETH_P_ARP)) | 745 | if (skb->protocol != htons(ETH_P_IPV6)) |
| 746 | return false; | 746 | return false; |
| 747 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) | 747 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) |
| 748 | return false; | 748 | return false; |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1a0dac2ef9ad..120eecc0f5a4 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2121,12 +2121,13 @@ EXPORT_SYMBOL(rtmsg_ifinfo); | |||
| 2121 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | 2121 | static int nlmsg_populate_fdb_fill(struct sk_buff *skb, |
| 2122 | struct net_device *dev, | 2122 | struct net_device *dev, |
| 2123 | u8 *addr, u32 pid, u32 seq, | 2123 | u8 *addr, u32 pid, u32 seq, |
| 2124 | int type, unsigned int flags) | 2124 | int type, unsigned int flags, |
| 2125 | int nlflags) | ||
| 2125 | { | 2126 | { |
| 2126 | struct nlmsghdr *nlh; | 2127 | struct nlmsghdr *nlh; |
| 2127 | struct ndmsg *ndm; | 2128 | struct ndmsg *ndm; |
| 2128 | 2129 | ||
| 2129 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI); | 2130 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), nlflags); |
| 2130 | if (!nlh) | 2131 | if (!nlh) |
| 2131 | return -EMSGSIZE; | 2132 | return -EMSGSIZE; |
| 2132 | 2133 | ||
| @@ -2164,7 +2165,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type) | |||
| 2164 | if (!skb) | 2165 | if (!skb) |
| 2165 | goto errout; | 2166 | goto errout; |
| 2166 | 2167 | ||
| 2167 | err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF); | 2168 | err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF, 0); |
| 2168 | if (err < 0) { | 2169 | if (err < 0) { |
| 2169 | kfree_skb(skb); | 2170 | kfree_skb(skb); |
| 2170 | goto errout; | 2171 | goto errout; |
| @@ -2389,7 +2390,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb, | |||
| 2389 | 2390 | ||
| 2390 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, | 2391 | err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, |
| 2391 | portid, seq, | 2392 | portid, seq, |
| 2392 | RTM_NEWNEIGH, NTF_SELF); | 2393 | RTM_NEWNEIGH, NTF_SELF, |
| 2394 | NLM_F_MULTI); | ||
| 2393 | if (err < 0) | 2395 | if (err < 0) |
| 2394 | return err; | 2396 | return err; |
| 2395 | skip: | 2397 | skip: |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 869c7afe3b07..90b96a11b974 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -2127,25 +2127,31 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen); | |||
| 2127 | * | 2127 | * |
| 2128 | * The `hlen` as calculated by skb_zerocopy_headlen() specifies the | 2128 | * The `hlen` as calculated by skb_zerocopy_headlen() specifies the |
| 2129 | * headroom in the `to` buffer. | 2129 | * headroom in the `to` buffer. |
| 2130 | * | ||
| 2131 | * Return value: | ||
| 2132 | * 0: everything is OK | ||
| 2133 | * -ENOMEM: couldn't orphan frags of @from due to lack of memory | ||
| 2134 | * -EFAULT: skb_copy_bits() found some problem with skb geometry | ||
| 2130 | */ | 2135 | */ |
| 2131 | void | 2136 | int |
| 2132 | skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | 2137 | skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen) |
| 2133 | { | 2138 | { |
| 2134 | int i, j = 0; | 2139 | int i, j = 0; |
| 2135 | int plen = 0; /* length of skb->head fragment */ | 2140 | int plen = 0; /* length of skb->head fragment */ |
| 2141 | int ret; | ||
| 2136 | struct page *page; | 2142 | struct page *page; |
| 2137 | unsigned int offset; | 2143 | unsigned int offset; |
| 2138 | 2144 | ||
| 2139 | BUG_ON(!from->head_frag && !hlen); | 2145 | BUG_ON(!from->head_frag && !hlen); |
| 2140 | 2146 | ||
| 2141 | /* dont bother with small payloads */ | 2147 | /* dont bother with small payloads */ |
| 2142 | if (len <= skb_tailroom(to)) { | 2148 | if (len <= skb_tailroom(to)) |
| 2143 | skb_copy_bits(from, 0, skb_put(to, len), len); | 2149 | return skb_copy_bits(from, 0, skb_put(to, len), len); |
| 2144 | return; | ||
| 2145 | } | ||
| 2146 | 2150 | ||
| 2147 | if (hlen) { | 2151 | if (hlen) { |
| 2148 | skb_copy_bits(from, 0, skb_put(to, hlen), hlen); | 2152 | ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen); |
| 2153 | if (unlikely(ret)) | ||
| 2154 | return ret; | ||
| 2149 | len -= hlen; | 2155 | len -= hlen; |
| 2150 | } else { | 2156 | } else { |
| 2151 | plen = min_t(int, skb_headlen(from), len); | 2157 | plen = min_t(int, skb_headlen(from), len); |
| @@ -2163,6 +2169,11 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
| 2163 | to->len += len + plen; | 2169 | to->len += len + plen; |
| 2164 | to->data_len += len + plen; | 2170 | to->data_len += len + plen; |
| 2165 | 2171 | ||
| 2172 | if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) { | ||
| 2173 | skb_tx_error(from); | ||
| 2174 | return -ENOMEM; | ||
| 2175 | } | ||
| 2176 | |||
| 2166 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { | 2177 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { |
| 2167 | if (!len) | 2178 | if (!len) |
| 2168 | break; | 2179 | break; |
| @@ -2173,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
| 2173 | j++; | 2184 | j++; |
| 2174 | } | 2185 | } |
| 2175 | skb_shinfo(to)->nr_frags = j; | 2186 | skb_shinfo(to)->nr_frags = j; |
| 2187 | |||
| 2188 | return 0; | ||
| 2176 | } | 2189 | } |
| 2177 | EXPORT_SYMBOL_GPL(skb_zerocopy); | 2190 | EXPORT_SYMBOL_GPL(skb_zerocopy); |
| 2178 | 2191 | ||
| @@ -2866,8 +2879,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, | |||
| 2866 | int err = -ENOMEM; | 2879 | int err = -ENOMEM; |
| 2867 | int i = 0; | 2880 | int i = 0; |
| 2868 | int pos; | 2881 | int pos; |
| 2882 | int dummy; | ||
| 2869 | 2883 | ||
| 2870 | proto = skb_network_protocol(head_skb); | 2884 | proto = skb_network_protocol(head_skb, &dummy); |
| 2871 | if (unlikely(!proto)) | 2885 | if (unlikely(!proto)) |
| 2872 | return ERR_PTR(-EINVAL); | 2886 | return ERR_PTR(-EINVAL); |
| 2873 | 2887 | ||
