diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 32 | ||||
-rw-r--r-- | net/core/drop_monitor.c | 2 | ||||
-rw-r--r-- | net/core/filter.c | 21 | ||||
-rw-r--r-- | net/core/flow_dissector.c | 85 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 20 | ||||
-rw-r--r-- | net/core/netpoll.c | 3 | ||||
-rw-r--r-- | net/core/pktgen.c | 111 | ||||
-rw-r--r-- | net/core/ptp_classifier.c | 64 | ||||
-rw-r--r-- | net/core/request_sock.c | 43 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 101 | ||||
-rw-r--r-- | net/core/timestamping.c | 57 |
11 files changed, 320 insertions, 219 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 7990984ca364..138ab897de7d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1085,6 +1085,7 @@ static int dev_get_valid_name(struct net *net, | |||
1085 | */ | 1085 | */ |
1086 | int dev_change_name(struct net_device *dev, const char *newname) | 1086 | int dev_change_name(struct net_device *dev, const char *newname) |
1087 | { | 1087 | { |
1088 | unsigned char old_assign_type; | ||
1088 | char oldname[IFNAMSIZ]; | 1089 | char oldname[IFNAMSIZ]; |
1089 | int err = 0; | 1090 | int err = 0; |
1090 | int ret; | 1091 | int ret; |
@@ -1112,10 +1113,14 @@ int dev_change_name(struct net_device *dev, const char *newname) | |||
1112 | return err; | 1113 | return err; |
1113 | } | 1114 | } |
1114 | 1115 | ||
1116 | old_assign_type = dev->name_assign_type; | ||
1117 | dev->name_assign_type = NET_NAME_RENAMED; | ||
1118 | |||
1115 | rollback: | 1119 | rollback: |
1116 | ret = device_rename(&dev->dev, dev->name); | 1120 | ret = device_rename(&dev->dev, dev->name); |
1117 | if (ret) { | 1121 | if (ret) { |
1118 | memcpy(dev->name, oldname, IFNAMSIZ); | 1122 | memcpy(dev->name, oldname, IFNAMSIZ); |
1123 | dev->name_assign_type = old_assign_type; | ||
1119 | write_seqcount_end(&devnet_rename_seq); | 1124 | write_seqcount_end(&devnet_rename_seq); |
1120 | return ret; | 1125 | return ret; |
1121 | } | 1126 | } |
@@ -1144,6 +1149,8 @@ rollback: | |||
1144 | write_seqcount_begin(&devnet_rename_seq); | 1149 | write_seqcount_begin(&devnet_rename_seq); |
1145 | memcpy(dev->name, oldname, IFNAMSIZ); | 1150 | memcpy(dev->name, oldname, IFNAMSIZ); |
1146 | memcpy(oldname, newname, IFNAMSIZ); | 1151 | memcpy(oldname, newname, IFNAMSIZ); |
1152 | dev->name_assign_type = old_assign_type; | ||
1153 | old_assign_type = NET_NAME_RENAMED; | ||
1147 | goto rollback; | 1154 | goto rollback; |
1148 | } else { | 1155 | } else { |
1149 | pr_err("%s: name change rollback failed: %d\n", | 1156 | pr_err("%s: name change rollback failed: %d\n", |
@@ -2745,8 +2752,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | |||
2745 | /* | 2752 | /* |
2746 | * Heuristic to force contended enqueues to serialize on a | 2753 | * Heuristic to force contended enqueues to serialize on a |
2747 | * separate lock before trying to get qdisc main lock. | 2754 | * separate lock before trying to get qdisc main lock. |
2748 | * This permits __QDISC_STATE_RUNNING owner to get the lock more often | 2755 | * This permits __QDISC___STATE_RUNNING owner to get the lock more |
2749 | * and dequeue packets faster. | 2756 | * often and dequeue packets faster. |
2750 | */ | 2757 | */ |
2751 | contended = qdisc_is_running(q); | 2758 | contended = qdisc_is_running(q); |
2752 | if (unlikely(contended)) | 2759 | if (unlikely(contended)) |
@@ -5438,13 +5445,9 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags) | |||
5438 | */ | 5445 | */ |
5439 | 5446 | ||
5440 | ret = 0; | 5447 | ret = 0; |
5441 | if ((old_flags ^ flags) & IFF_UP) { /* Bit is different ? */ | 5448 | if ((old_flags ^ flags) & IFF_UP) |
5442 | ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); | 5449 | ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); |
5443 | 5450 | ||
5444 | if (!ret) | ||
5445 | dev_set_rx_mode(dev); | ||
5446 | } | ||
5447 | |||
5448 | if ((flags ^ dev->gflags) & IFF_PROMISC) { | 5451 | if ((flags ^ dev->gflags) & IFF_PROMISC) { |
5449 | int inc = (flags & IFF_PROMISC) ? 1 : -1; | 5452 | int inc = (flags & IFF_PROMISC) ? 1 : -1; |
5450 | unsigned int old_flags = dev->flags; | 5453 | unsigned int old_flags = dev->flags; |
@@ -6444,17 +6447,19 @@ void netdev_freemem(struct net_device *dev) | |||
6444 | 6447 | ||
6445 | /** | 6448 | /** |
6446 | * alloc_netdev_mqs - allocate network device | 6449 | * alloc_netdev_mqs - allocate network device |
6447 | * @sizeof_priv: size of private data to allocate space for | 6450 | * @sizeof_priv: size of private data to allocate space for |
6448 | * @name: device name format string | 6451 | * @name: device name format string |
6449 | * @setup: callback to initialize device | 6452 | * @name_assign_type: origin of device name |
6450 | * @txqs: the number of TX subqueues to allocate | 6453 | * @setup: callback to initialize device |
6451 | * @rxqs: the number of RX subqueues to allocate | 6454 | * @txqs: the number of TX subqueues to allocate |
6455 | * @rxqs: the number of RX subqueues to allocate | ||
6452 | * | 6456 | * |
6453 | * Allocates a struct net_device with private data area for driver use | 6457 | * Allocates a struct net_device with private data area for driver use |
6454 | * and performs basic initialization. Also allocates subqueue structs | 6458 | * and performs basic initialization. Also allocates subqueue structs |
6455 | * for each queue on the device. | 6459 | * for each queue on the device. |
6456 | */ | 6460 | */ |
6457 | struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | 6461 | struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, |
6462 | unsigned char name_assign_type, | ||
6458 | void (*setup)(struct net_device *), | 6463 | void (*setup)(struct net_device *), |
6459 | unsigned int txqs, unsigned int rxqs) | 6464 | unsigned int txqs, unsigned int rxqs) |
6460 | { | 6465 | { |
@@ -6533,6 +6538,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
6533 | #endif | 6538 | #endif |
6534 | 6539 | ||
6535 | strcpy(dev->name, name); | 6540 | strcpy(dev->name, name); |
6541 | dev->name_assign_type = name_assign_type; | ||
6536 | dev->group = INIT_NETDEV_GROUP; | 6542 | dev->group = INIT_NETDEV_GROUP; |
6537 | if (!dev->ethtool_ops) | 6543 | if (!dev->ethtool_ops) |
6538 | dev->ethtool_ops = &default_ethtool_ops; | 6544 | dev->ethtool_ops = &default_ethtool_ops; |
@@ -7101,7 +7107,7 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list) | |||
7101 | rtnl_lock_unregistering(net_list); | 7107 | rtnl_lock_unregistering(net_list); |
7102 | list_for_each_entry(net, net_list, exit_list) { | 7108 | list_for_each_entry(net, net_list, exit_list) { |
7103 | for_each_netdev_reverse(net, dev) { | 7109 | for_each_netdev_reverse(net, dev) { |
7104 | if (dev->rtnl_link_ops) | 7110 | if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) |
7105 | dev->rtnl_link_ops->dellink(dev, &dev_kill_list); | 7111 | dev->rtnl_link_ops->dellink(dev, &dev_kill_list); |
7106 | else | 7112 | else |
7107 | unregister_netdevice_queue(dev, &dev_kill_list); | 7113 | unregister_netdevice_queue(dev, &dev_kill_list); |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index e70301eb7a4a..50f9a9db5792 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -289,10 +289,8 @@ static int net_dm_cmd_trace(struct sk_buff *skb, | |||
289 | switch (info->genlhdr->cmd) { | 289 | switch (info->genlhdr->cmd) { |
290 | case NET_DM_CMD_START: | 290 | case NET_DM_CMD_START: |
291 | return set_all_monitor_traces(TRACE_ON); | 291 | return set_all_monitor_traces(TRACE_ON); |
292 | break; | ||
293 | case NET_DM_CMD_STOP: | 292 | case NET_DM_CMD_STOP: |
294 | return set_all_monitor_traces(TRACE_OFF); | 293 | return set_all_monitor_traces(TRACE_OFF); |
295 | break; | ||
296 | } | 294 | } |
297 | 295 | ||
298 | return -ENOTSUPP; | 296 | return -ENOTSUPP; |
diff --git a/net/core/filter.c b/net/core/filter.c index 1dbf6462f766..b90ae7fb3b89 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -84,15 +84,6 @@ void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, uns | |||
84 | return NULL; | 84 | return NULL; |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline void *load_pointer(const struct sk_buff *skb, int k, | ||
88 | unsigned int size, void *buffer) | ||
89 | { | ||
90 | if (k >= 0) | ||
91 | return skb_header_pointer(skb, k, size, buffer); | ||
92 | |||
93 | return bpf_internal_load_pointer_neg_helper(skb, k, size); | ||
94 | } | ||
95 | |||
96 | /** | 87 | /** |
97 | * sk_filter - run a packet through a socket filter | 88 | * sk_filter - run a packet through a socket filter |
98 | * @sk: sock associated with &sk_buff | 89 | * @sk: sock associated with &sk_buff |
@@ -537,7 +528,7 @@ load_word: | |||
537 | * BPF_R0 - 8/16/32-bit skb data converted to cpu endianness | 528 | * BPF_R0 - 8/16/32-bit skb data converted to cpu endianness |
538 | */ | 529 | */ |
539 | 530 | ||
540 | ptr = load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &tmp); | 531 | ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &tmp); |
541 | if (likely(ptr != NULL)) { | 532 | if (likely(ptr != NULL)) { |
542 | BPF_R0 = get_unaligned_be32(ptr); | 533 | BPF_R0 = get_unaligned_be32(ptr); |
543 | CONT; | 534 | CONT; |
@@ -547,7 +538,7 @@ load_word: | |||
547 | LD_ABS_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + imm32)) */ | 538 | LD_ABS_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + imm32)) */ |
548 | off = IMM; | 539 | off = IMM; |
549 | load_half: | 540 | load_half: |
550 | ptr = load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &tmp); | 541 | ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &tmp); |
551 | if (likely(ptr != NULL)) { | 542 | if (likely(ptr != NULL)) { |
552 | BPF_R0 = get_unaligned_be16(ptr); | 543 | BPF_R0 = get_unaligned_be16(ptr); |
553 | CONT; | 544 | CONT; |
@@ -557,7 +548,7 @@ load_half: | |||
557 | LD_ABS_B: /* BPF_R0 = *(u8 *) (skb->data + imm32) */ | 548 | LD_ABS_B: /* BPF_R0 = *(u8 *) (skb->data + imm32) */ |
558 | off = IMM; | 549 | off = IMM; |
559 | load_byte: | 550 | load_byte: |
560 | ptr = load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &tmp); | 551 | ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &tmp); |
561 | if (likely(ptr != NULL)) { | 552 | if (likely(ptr != NULL)) { |
562 | BPF_R0 = *(u8 *)ptr; | 553 | BPF_R0 = *(u8 *)ptr; |
563 | CONT; | 554 | CONT; |
@@ -1094,7 +1085,7 @@ err: | |||
1094 | * a cell if not previously written, and we check all branches to be sure | 1085 | * a cell if not previously written, and we check all branches to be sure |
1095 | * a malicious user doesn't try to abuse us. | 1086 | * a malicious user doesn't try to abuse us. |
1096 | */ | 1087 | */ |
1097 | static int check_load_and_stores(struct sock_filter *filter, int flen) | 1088 | static int check_load_and_stores(const struct sock_filter *filter, int flen) |
1098 | { | 1089 | { |
1099 | u16 *masks, memvalid = 0; /* One bit per cell, 16 cells */ | 1090 | u16 *masks, memvalid = 0; /* One bit per cell, 16 cells */ |
1100 | int pc, ret = 0; | 1091 | int pc, ret = 0; |
@@ -1227,7 +1218,7 @@ static bool chk_code_allowed(u16 code_to_probe) | |||
1227 | * | 1218 | * |
1228 | * Returns 0 if the rule set is legal or -EINVAL if not. | 1219 | * Returns 0 if the rule set is legal or -EINVAL if not. |
1229 | */ | 1220 | */ |
1230 | int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | 1221 | int sk_chk_filter(const struct sock_filter *filter, unsigned int flen) |
1231 | { | 1222 | { |
1232 | bool anc_found; | 1223 | bool anc_found; |
1233 | int pc; | 1224 | int pc; |
@@ -1237,7 +1228,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | |||
1237 | 1228 | ||
1238 | /* Check the filter code now */ | 1229 | /* Check the filter code now */ |
1239 | for (pc = 0; pc < flen; pc++) { | 1230 | for (pc = 0; pc < flen; pc++) { |
1240 | struct sock_filter *ftest = &filter[pc]; | 1231 | const struct sock_filter *ftest = &filter[pc]; |
1241 | 1232 | ||
1242 | /* May we actually operate on this code? */ | 1233 | /* May we actually operate on this code? */ |
1243 | if (!chk_code_allowed(ftest->code)) | 1234 | if (!chk_code_allowed(ftest->code)) |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 107ed12a5323..5f362c1d0332 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -80,6 +80,8 @@ ip: | |||
80 | case htons(ETH_P_IPV6): { | 80 | case htons(ETH_P_IPV6): { |
81 | const struct ipv6hdr *iph; | 81 | const struct ipv6hdr *iph; |
82 | struct ipv6hdr _iph; | 82 | struct ipv6hdr _iph; |
83 | __be32 flow_label; | ||
84 | |||
83 | ipv6: | 85 | ipv6: |
84 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | 86 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); |
85 | if (!iph) | 87 | if (!iph) |
@@ -89,6 +91,21 @@ ipv6: | |||
89 | flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr); | 91 | flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr); |
90 | flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr); | 92 | flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr); |
91 | nhoff += sizeof(struct ipv6hdr); | 93 | nhoff += sizeof(struct ipv6hdr); |
94 | |||
95 | flow_label = ip6_flowlabel(iph); | ||
96 | if (flow_label) { | ||
97 | /* Awesome, IPv6 packet has a flow label so we can | ||
98 | * use that to represent the ports without any | ||
99 | * further dissection. | ||
100 | */ | ||
101 | flow->n_proto = proto; | ||
102 | flow->ip_proto = ip_proto; | ||
103 | flow->ports = flow_label; | ||
104 | flow->thoff = (u16)nhoff; | ||
105 | |||
106 | return true; | ||
107 | } | ||
108 | |||
92 | break; | 109 | break; |
93 | } | 110 | } |
94 | case htons(ETH_P_8021AD): | 111 | case htons(ETH_P_8021AD): |
@@ -175,6 +192,7 @@ ipv6: | |||
175 | break; | 192 | break; |
176 | } | 193 | } |
177 | 194 | ||
195 | flow->n_proto = proto; | ||
178 | flow->ip_proto = ip_proto; | 196 | flow->ip_proto = ip_proto; |
179 | flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto); | 197 | flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto); |
180 | flow->thoff = (u16) nhoff; | 198 | flow->thoff = (u16) nhoff; |
@@ -195,12 +213,33 @@ static __always_inline u32 __flow_hash_3words(u32 a, u32 b, u32 c) | |||
195 | return jhash_3words(a, b, c, hashrnd); | 213 | return jhash_3words(a, b, c, hashrnd); |
196 | } | 214 | } |
197 | 215 | ||
198 | static __always_inline u32 __flow_hash_1word(u32 a) | 216 | static inline u32 __flow_hash_from_keys(struct flow_keys *keys) |
199 | { | 217 | { |
200 | __flow_hash_secret_init(); | 218 | u32 hash; |
201 | return jhash_1word(a, hashrnd); | 219 | |
220 | /* get a consistent hash (same value on both flow directions) */ | ||
221 | if (((__force u32)keys->dst < (__force u32)keys->src) || | ||
222 | (((__force u32)keys->dst == (__force u32)keys->src) && | ||
223 | ((__force u16)keys->port16[1] < (__force u16)keys->port16[0]))) { | ||
224 | swap(keys->dst, keys->src); | ||
225 | swap(keys->port16[0], keys->port16[1]); | ||
226 | } | ||
227 | |||
228 | hash = __flow_hash_3words((__force u32)keys->dst, | ||
229 | (__force u32)keys->src, | ||
230 | (__force u32)keys->ports); | ||
231 | if (!hash) | ||
232 | hash = 1; | ||
233 | |||
234 | return hash; | ||
202 | } | 235 | } |
203 | 236 | ||
237 | u32 flow_hash_from_keys(struct flow_keys *keys) | ||
238 | { | ||
239 | return __flow_hash_from_keys(keys); | ||
240 | } | ||
241 | EXPORT_SYMBOL(flow_hash_from_keys); | ||
242 | |||
204 | /* | 243 | /* |
205 | * __skb_get_hash: calculate a flow hash based on src/dst addresses | 244 | * __skb_get_hash: calculate a flow hash based on src/dst addresses |
206 | * and src/dst port numbers. Sets hash in skb to non-zero hash value | 245 | * and src/dst port numbers. Sets hash in skb to non-zero hash value |
@@ -210,7 +249,6 @@ static __always_inline u32 __flow_hash_1word(u32 a) | |||
210 | void __skb_get_hash(struct sk_buff *skb) | 249 | void __skb_get_hash(struct sk_buff *skb) |
211 | { | 250 | { |
212 | struct flow_keys keys; | 251 | struct flow_keys keys; |
213 | u32 hash; | ||
214 | 252 | ||
215 | if (!skb_flow_dissect(skb, &keys)) | 253 | if (!skb_flow_dissect(skb, &keys)) |
216 | return; | 254 | return; |
@@ -218,21 +256,9 @@ void __skb_get_hash(struct sk_buff *skb) | |||
218 | if (keys.ports) | 256 | if (keys.ports) |
219 | skb->l4_hash = 1; | 257 | skb->l4_hash = 1; |
220 | 258 | ||
221 | /* get a consistent hash (same value on both flow directions) */ | 259 | skb->sw_hash = 1; |
222 | if (((__force u32)keys.dst < (__force u32)keys.src) || | ||
223 | (((__force u32)keys.dst == (__force u32)keys.src) && | ||
224 | ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { | ||
225 | swap(keys.dst, keys.src); | ||
226 | swap(keys.port16[0], keys.port16[1]); | ||
227 | } | ||
228 | |||
229 | hash = __flow_hash_3words((__force u32)keys.dst, | ||
230 | (__force u32)keys.src, | ||
231 | (__force u32)keys.ports); | ||
232 | if (!hash) | ||
233 | hash = 1; | ||
234 | 260 | ||
235 | skb->hash = hash; | 261 | skb->hash = __flow_hash_from_keys(&keys); |
236 | } | 262 | } |
237 | EXPORT_SYMBOL(__skb_get_hash); | 263 | EXPORT_SYMBOL(__skb_get_hash); |
238 | 264 | ||
@@ -240,7 +266,7 @@ EXPORT_SYMBOL(__skb_get_hash); | |||
240 | * Returns a Tx hash based on the given packet descriptor a Tx queues' number | 266 | * Returns a Tx hash based on the given packet descriptor a Tx queues' number |
241 | * to be used as a distribution range. | 267 | * to be used as a distribution range. |
242 | */ | 268 | */ |
243 | u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, | 269 | u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb, |
244 | unsigned int num_tx_queues) | 270 | unsigned int num_tx_queues) |
245 | { | 271 | { |
246 | u32 hash; | 272 | u32 hash; |
@@ -260,13 +286,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, | |||
260 | qcount = dev->tc_to_txq[tc].count; | 286 | qcount = dev->tc_to_txq[tc].count; |
261 | } | 287 | } |
262 | 288 | ||
263 | if (skb->sk && skb->sk->sk_hash) | 289 | return (u16) (((u64)skb_get_hash(skb) * qcount) >> 32) + qoffset; |
264 | hash = skb->sk->sk_hash; | ||
265 | else | ||
266 | hash = (__force u16) skb->protocol; | ||
267 | hash = __flow_hash_1word(hash); | ||
268 | |||
269 | return (u16) (((u64) hash * qcount) >> 32) + qoffset; | ||
270 | } | 290 | } |
271 | EXPORT_SYMBOL(__skb_tx_hash); | 291 | EXPORT_SYMBOL(__skb_tx_hash); |
272 | 292 | ||
@@ -338,17 +358,10 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) | |||
338 | if (map) { | 358 | if (map) { |
339 | if (map->len == 1) | 359 | if (map->len == 1) |
340 | queue_index = map->queues[0]; | 360 | queue_index = map->queues[0]; |
341 | else { | 361 | else |
342 | u32 hash; | ||
343 | if (skb->sk && skb->sk->sk_hash) | ||
344 | hash = skb->sk->sk_hash; | ||
345 | else | ||
346 | hash = (__force u16) skb->protocol ^ | ||
347 | skb->hash; | ||
348 | hash = __flow_hash_1word(hash); | ||
349 | queue_index = map->queues[ | 362 | queue_index = map->queues[ |
350 | ((u64)hash * map->len) >> 32]; | 363 | ((u64)skb_get_hash(skb) * map->len) >> 32]; |
351 | } | 364 | |
352 | if (unlikely(queue_index >= dev->real_num_tx_queues)) | 365 | if (unlikely(queue_index >= dev->real_num_tx_queues)) |
353 | queue_index = -1; | 366 | queue_index = -1; |
354 | } | 367 | } |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 1cac29ebb05b..7752f2ad49a5 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -112,6 +112,25 @@ NETDEVICE_SHOW_RO(ifindex, fmt_dec); | |||
112 | NETDEVICE_SHOW_RO(type, fmt_dec); | 112 | NETDEVICE_SHOW_RO(type, fmt_dec); |
113 | NETDEVICE_SHOW_RO(link_mode, fmt_dec); | 113 | NETDEVICE_SHOW_RO(link_mode, fmt_dec); |
114 | 114 | ||
115 | static ssize_t format_name_assign_type(const struct net_device *net, char *buf) | ||
116 | { | ||
117 | return sprintf(buf, fmt_dec, net->name_assign_type); | ||
118 | } | ||
119 | |||
120 | static ssize_t name_assign_type_show(struct device *dev, | ||
121 | struct device_attribute *attr, | ||
122 | char *buf) | ||
123 | { | ||
124 | struct net_device *net = to_net_dev(dev); | ||
125 | ssize_t ret = -EINVAL; | ||
126 | |||
127 | if (net->name_assign_type != NET_NAME_UNKNOWN) | ||
128 | ret = netdev_show(dev, attr, buf, format_name_assign_type); | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | static DEVICE_ATTR_RO(name_assign_type); | ||
133 | |||
115 | /* use same locking rules as GIFHWADDR ioctl's */ | 134 | /* use same locking rules as GIFHWADDR ioctl's */ |
116 | static ssize_t address_show(struct device *dev, struct device_attribute *attr, | 135 | static ssize_t address_show(struct device *dev, struct device_attribute *attr, |
117 | char *buf) | 136 | char *buf) |
@@ -387,6 +406,7 @@ static struct attribute *net_class_attrs[] = { | |||
387 | &dev_attr_dev_port.attr, | 406 | &dev_attr_dev_port.attr, |
388 | &dev_attr_iflink.attr, | 407 | &dev_attr_iflink.attr, |
389 | &dev_attr_ifindex.attr, | 408 | &dev_attr_ifindex.attr, |
409 | &dev_attr_name_assign_type.attr, | ||
390 | &dev_attr_addr_assign_type.attr, | 410 | &dev_attr_addr_assign_type.attr, |
391 | &dev_attr_addr_len.attr, | 411 | &dev_attr_addr_len.attr, |
392 | &dev_attr_link_mode.attr, | 412 | &dev_attr_link_mode.attr, |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e33937fb32a0..907fb5e36c02 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -822,7 +822,8 @@ void __netpoll_cleanup(struct netpoll *np) | |||
822 | 822 | ||
823 | RCU_INIT_POINTER(np->dev->npinfo, NULL); | 823 | RCU_INIT_POINTER(np->dev->npinfo, NULL); |
824 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); | 824 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); |
825 | } | 825 | } else |
826 | RCU_INIT_POINTER(np->dev->npinfo, NULL); | ||
826 | } | 827 | } |
827 | EXPORT_SYMBOL_GPL(__netpoll_cleanup); | 828 | EXPORT_SYMBOL_GPL(__netpoll_cleanup); |
828 | 829 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index fc17a9d309ac..8b849ddfef2e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -69,8 +69,9 @@ | |||
69 | * for running devices in the if_list and sends packets until count is 0 it | 69 | * for running devices in the if_list and sends packets until count is 0 it |
70 | * also the thread checks the thread->control which is used for inter-process | 70 | * also the thread checks the thread->control which is used for inter-process |
71 | * communication. controlling process "posts" operations to the threads this | 71 | * communication. controlling process "posts" operations to the threads this |
72 | * way. The if_lock should be possible to remove when add/rem_device is merged | 72 | * way. |
73 | * into this too. | 73 | * The if_list is RCU protected, and the if_lock remains to protect updating |
74 | * of if_list, from "add_device" as it invoked from userspace (via proc write). | ||
74 | * | 75 | * |
75 | * By design there should only be *one* "controlling" process. In practice | 76 | * By design there should only be *one* "controlling" process. In practice |
76 | * multiple write accesses gives unpredictable result. Understood by "write" | 77 | * multiple write accesses gives unpredictable result. Understood by "write" |
@@ -208,7 +209,7 @@ | |||
208 | #define T_REMDEVALL (1<<2) /* Remove all devs */ | 209 | #define T_REMDEVALL (1<<2) /* Remove all devs */ |
209 | #define T_REMDEV (1<<3) /* Remove one dev */ | 210 | #define T_REMDEV (1<<3) /* Remove one dev */ |
210 | 211 | ||
211 | /* If lock -- can be removed after some work */ | 212 | /* If lock -- protects updating of if_list */ |
212 | #define if_lock(t) spin_lock(&(t->if_lock)); | 213 | #define if_lock(t) spin_lock(&(t->if_lock)); |
213 | #define if_unlock(t) spin_unlock(&(t->if_lock)); | 214 | #define if_unlock(t) spin_unlock(&(t->if_lock)); |
214 | 215 | ||
@@ -241,6 +242,7 @@ struct pktgen_dev { | |||
241 | struct proc_dir_entry *entry; /* proc file */ | 242 | struct proc_dir_entry *entry; /* proc file */ |
242 | struct pktgen_thread *pg_thread;/* the owner */ | 243 | struct pktgen_thread *pg_thread;/* the owner */ |
243 | struct list_head list; /* chaining in the thread's run-queue */ | 244 | struct list_head list; /* chaining in the thread's run-queue */ |
245 | struct rcu_head rcu; /* freed by RCU */ | ||
244 | 246 | ||
245 | int running; /* if false, the test will stop */ | 247 | int running; /* if false, the test will stop */ |
246 | 248 | ||
@@ -802,7 +804,6 @@ static int strn_len(const char __user * user_buffer, unsigned int maxlen) | |||
802 | case '\t': | 804 | case '\t': |
803 | case ' ': | 805 | case ' ': |
804 | goto done_str; | 806 | goto done_str; |
805 | break; | ||
806 | default: | 807 | default: |
807 | break; | 808 | break; |
808 | } | 809 | } |
@@ -1737,14 +1738,14 @@ static int pktgen_thread_show(struct seq_file *seq, void *v) | |||
1737 | 1738 | ||
1738 | seq_puts(seq, "Running: "); | 1739 | seq_puts(seq, "Running: "); |
1739 | 1740 | ||
1740 | if_lock(t); | 1741 | rcu_read_lock(); |
1741 | list_for_each_entry(pkt_dev, &t->if_list, list) | 1742 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) |
1742 | if (pkt_dev->running) | 1743 | if (pkt_dev->running) |
1743 | seq_printf(seq, "%s ", pkt_dev->odevname); | 1744 | seq_printf(seq, "%s ", pkt_dev->odevname); |
1744 | 1745 | ||
1745 | seq_puts(seq, "\nStopped: "); | 1746 | seq_puts(seq, "\nStopped: "); |
1746 | 1747 | ||
1747 | list_for_each_entry(pkt_dev, &t->if_list, list) | 1748 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) |
1748 | if (!pkt_dev->running) | 1749 | if (!pkt_dev->running) |
1749 | seq_printf(seq, "%s ", pkt_dev->odevname); | 1750 | seq_printf(seq, "%s ", pkt_dev->odevname); |
1750 | 1751 | ||
@@ -1753,7 +1754,7 @@ static int pktgen_thread_show(struct seq_file *seq, void *v) | |||
1753 | else | 1754 | else |
1754 | seq_puts(seq, "\nResult: NA\n"); | 1755 | seq_puts(seq, "\nResult: NA\n"); |
1755 | 1756 | ||
1756 | if_unlock(t); | 1757 | rcu_read_unlock(); |
1757 | 1758 | ||
1758 | return 0; | 1759 | return 0; |
1759 | } | 1760 | } |
@@ -1878,10 +1879,8 @@ static struct pktgen_dev *__pktgen_NN_threads(const struct pktgen_net *pn, | |||
1878 | pkt_dev = pktgen_find_dev(t, ifname, exact); | 1879 | pkt_dev = pktgen_find_dev(t, ifname, exact); |
1879 | if (pkt_dev) { | 1880 | if (pkt_dev) { |
1880 | if (remove) { | 1881 | if (remove) { |
1881 | if_lock(t); | ||
1882 | pkt_dev->removal_mark = 1; | 1882 | pkt_dev->removal_mark = 1; |
1883 | t->control |= T_REMDEV; | 1883 | t->control |= T_REMDEV; |
1884 | if_unlock(t); | ||
1885 | } | 1884 | } |
1886 | break; | 1885 | break; |
1887 | } | 1886 | } |
@@ -1931,7 +1930,8 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d | |||
1931 | list_for_each_entry(t, &pn->pktgen_threads, th_list) { | 1930 | list_for_each_entry(t, &pn->pktgen_threads, th_list) { |
1932 | struct pktgen_dev *pkt_dev; | 1931 | struct pktgen_dev *pkt_dev; |
1933 | 1932 | ||
1934 | list_for_each_entry(pkt_dev, &t->if_list, list) { | 1933 | rcu_read_lock(); |
1934 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { | ||
1935 | if (pkt_dev->odev != dev) | 1935 | if (pkt_dev->odev != dev) |
1936 | continue; | 1936 | continue; |
1937 | 1937 | ||
@@ -1946,6 +1946,7 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d | |||
1946 | dev->name); | 1946 | dev->name); |
1947 | break; | 1947 | break; |
1948 | } | 1948 | } |
1949 | rcu_read_unlock(); | ||
1949 | } | 1950 | } |
1950 | } | 1951 | } |
1951 | 1952 | ||
@@ -2997,8 +2998,8 @@ static void pktgen_run(struct pktgen_thread *t) | |||
2997 | 2998 | ||
2998 | func_enter(); | 2999 | func_enter(); |
2999 | 3000 | ||
3000 | if_lock(t); | 3001 | rcu_read_lock(); |
3001 | list_for_each_entry(pkt_dev, &t->if_list, list) { | 3002 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { |
3002 | 3003 | ||
3003 | /* | 3004 | /* |
3004 | * setup odev and create initial packet. | 3005 | * setup odev and create initial packet. |
@@ -3007,18 +3008,18 @@ static void pktgen_run(struct pktgen_thread *t) | |||
3007 | 3008 | ||
3008 | if (pkt_dev->odev) { | 3009 | if (pkt_dev->odev) { |
3009 | pktgen_clear_counters(pkt_dev); | 3010 | pktgen_clear_counters(pkt_dev); |
3010 | pkt_dev->running = 1; /* Cranke yeself! */ | ||
3011 | pkt_dev->skb = NULL; | 3011 | pkt_dev->skb = NULL; |
3012 | pkt_dev->started_at = pkt_dev->next_tx = ktime_get(); | 3012 | pkt_dev->started_at = pkt_dev->next_tx = ktime_get(); |
3013 | 3013 | ||
3014 | set_pkt_overhead(pkt_dev); | 3014 | set_pkt_overhead(pkt_dev); |
3015 | 3015 | ||
3016 | strcpy(pkt_dev->result, "Starting"); | 3016 | strcpy(pkt_dev->result, "Starting"); |
3017 | pkt_dev->running = 1; /* Cranke yeself! */ | ||
3017 | started++; | 3018 | started++; |
3018 | } else | 3019 | } else |
3019 | strcpy(pkt_dev->result, "Error starting"); | 3020 | strcpy(pkt_dev->result, "Error starting"); |
3020 | } | 3021 | } |
3021 | if_unlock(t); | 3022 | rcu_read_unlock(); |
3022 | if (started) | 3023 | if (started) |
3023 | t->control &= ~(T_STOP); | 3024 | t->control &= ~(T_STOP); |
3024 | } | 3025 | } |
@@ -3041,27 +3042,25 @@ static int thread_is_running(const struct pktgen_thread *t) | |||
3041 | { | 3042 | { |
3042 | const struct pktgen_dev *pkt_dev; | 3043 | const struct pktgen_dev *pkt_dev; |
3043 | 3044 | ||
3044 | list_for_each_entry(pkt_dev, &t->if_list, list) | 3045 | rcu_read_lock(); |
3045 | if (pkt_dev->running) | 3046 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) |
3047 | if (pkt_dev->running) { | ||
3048 | rcu_read_unlock(); | ||
3046 | return 1; | 3049 | return 1; |
3050 | } | ||
3051 | rcu_read_unlock(); | ||
3047 | return 0; | 3052 | return 0; |
3048 | } | 3053 | } |
3049 | 3054 | ||
3050 | static int pktgen_wait_thread_run(struct pktgen_thread *t) | 3055 | static int pktgen_wait_thread_run(struct pktgen_thread *t) |
3051 | { | 3056 | { |
3052 | if_lock(t); | ||
3053 | |||
3054 | while (thread_is_running(t)) { | 3057 | while (thread_is_running(t)) { |
3055 | 3058 | ||
3056 | if_unlock(t); | ||
3057 | |||
3058 | msleep_interruptible(100); | 3059 | msleep_interruptible(100); |
3059 | 3060 | ||
3060 | if (signal_pending(current)) | 3061 | if (signal_pending(current)) |
3061 | goto signal; | 3062 | goto signal; |
3062 | if_lock(t); | ||
3063 | } | 3063 | } |
3064 | if_unlock(t); | ||
3065 | return 1; | 3064 | return 1; |
3066 | signal: | 3065 | signal: |
3067 | return 0; | 3066 | return 0; |
@@ -3166,10 +3165,10 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev) | |||
3166 | return -EINVAL; | 3165 | return -EINVAL; |
3167 | } | 3166 | } |
3168 | 3167 | ||
3168 | pkt_dev->running = 0; | ||
3169 | kfree_skb(pkt_dev->skb); | 3169 | kfree_skb(pkt_dev->skb); |
3170 | pkt_dev->skb = NULL; | 3170 | pkt_dev->skb = NULL; |
3171 | pkt_dev->stopped_at = ktime_get(); | 3171 | pkt_dev->stopped_at = ktime_get(); |
3172 | pkt_dev->running = 0; | ||
3173 | 3172 | ||
3174 | show_results(pkt_dev, nr_frags); | 3173 | show_results(pkt_dev, nr_frags); |
3175 | 3174 | ||
@@ -3180,9 +3179,8 @@ static struct pktgen_dev *next_to_run(struct pktgen_thread *t) | |||
3180 | { | 3179 | { |
3181 | struct pktgen_dev *pkt_dev, *best = NULL; | 3180 | struct pktgen_dev *pkt_dev, *best = NULL; |
3182 | 3181 | ||
3183 | if_lock(t); | 3182 | rcu_read_lock(); |
3184 | 3183 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { | |
3185 | list_for_each_entry(pkt_dev, &t->if_list, list) { | ||
3186 | if (!pkt_dev->running) | 3184 | if (!pkt_dev->running) |
3187 | continue; | 3185 | continue; |
3188 | if (best == NULL) | 3186 | if (best == NULL) |
@@ -3190,7 +3188,8 @@ static struct pktgen_dev *next_to_run(struct pktgen_thread *t) | |||
3190 | else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0) | 3188 | else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0) |
3191 | best = pkt_dev; | 3189 | best = pkt_dev; |
3192 | } | 3190 | } |
3193 | if_unlock(t); | 3191 | rcu_read_unlock(); |
3192 | |||
3194 | return best; | 3193 | return best; |
3195 | } | 3194 | } |
3196 | 3195 | ||
@@ -3200,13 +3199,13 @@ static void pktgen_stop(struct pktgen_thread *t) | |||
3200 | 3199 | ||
3201 | func_enter(); | 3200 | func_enter(); |
3202 | 3201 | ||
3203 | if_lock(t); | 3202 | rcu_read_lock(); |
3204 | 3203 | ||
3205 | list_for_each_entry(pkt_dev, &t->if_list, list) { | 3204 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { |
3206 | pktgen_stop_device(pkt_dev); | 3205 | pktgen_stop_device(pkt_dev); |
3207 | } | 3206 | } |
3208 | 3207 | ||
3209 | if_unlock(t); | 3208 | rcu_read_unlock(); |
3210 | } | 3209 | } |
3211 | 3210 | ||
3212 | /* | 3211 | /* |
@@ -3220,8 +3219,6 @@ static void pktgen_rem_one_if(struct pktgen_thread *t) | |||
3220 | 3219 | ||
3221 | func_enter(); | 3220 | func_enter(); |
3222 | 3221 | ||
3223 | if_lock(t); | ||
3224 | |||
3225 | list_for_each_safe(q, n, &t->if_list) { | 3222 | list_for_each_safe(q, n, &t->if_list) { |
3226 | cur = list_entry(q, struct pktgen_dev, list); | 3223 | cur = list_entry(q, struct pktgen_dev, list); |
3227 | 3224 | ||
@@ -3235,8 +3232,6 @@ static void pktgen_rem_one_if(struct pktgen_thread *t) | |||
3235 | 3232 | ||
3236 | break; | 3233 | break; |
3237 | } | 3234 | } |
3238 | |||
3239 | if_unlock(t); | ||
3240 | } | 3235 | } |
3241 | 3236 | ||
3242 | static void pktgen_rem_all_ifs(struct pktgen_thread *t) | 3237 | static void pktgen_rem_all_ifs(struct pktgen_thread *t) |
@@ -3248,8 +3243,6 @@ static void pktgen_rem_all_ifs(struct pktgen_thread *t) | |||
3248 | 3243 | ||
3249 | /* Remove all devices, free mem */ | 3244 | /* Remove all devices, free mem */ |
3250 | 3245 | ||
3251 | if_lock(t); | ||
3252 | |||
3253 | list_for_each_safe(q, n, &t->if_list) { | 3246 | list_for_each_safe(q, n, &t->if_list) { |
3254 | cur = list_entry(q, struct pktgen_dev, list); | 3247 | cur = list_entry(q, struct pktgen_dev, list); |
3255 | 3248 | ||
@@ -3258,8 +3251,6 @@ static void pktgen_rem_all_ifs(struct pktgen_thread *t) | |||
3258 | 3251 | ||
3259 | pktgen_remove_device(t, cur); | 3252 | pktgen_remove_device(t, cur); |
3260 | } | 3253 | } |
3261 | |||
3262 | if_unlock(t); | ||
3263 | } | 3254 | } |
3264 | 3255 | ||
3265 | static void pktgen_rem_thread(struct pktgen_thread *t) | 3256 | static void pktgen_rem_thread(struct pktgen_thread *t) |
@@ -3407,10 +3398,10 @@ static int pktgen_thread_worker(void *arg) | |||
3407 | 3398 | ||
3408 | pr_debug("starting pktgen/%d: pid=%d\n", cpu, task_pid_nr(current)); | 3399 | pr_debug("starting pktgen/%d: pid=%d\n", cpu, task_pid_nr(current)); |
3409 | 3400 | ||
3410 | set_current_state(TASK_INTERRUPTIBLE); | ||
3411 | |||
3412 | set_freezable(); | 3401 | set_freezable(); |
3413 | 3402 | ||
3403 | __set_current_state(TASK_RUNNING); | ||
3404 | |||
3414 | while (!kthread_should_stop()) { | 3405 | while (!kthread_should_stop()) { |
3415 | pkt_dev = next_to_run(t); | 3406 | pkt_dev = next_to_run(t); |
3416 | 3407 | ||
@@ -3424,8 +3415,6 @@ static int pktgen_thread_worker(void *arg) | |||
3424 | continue; | 3415 | continue; |
3425 | } | 3416 | } |
3426 | 3417 | ||
3427 | __set_current_state(TASK_RUNNING); | ||
3428 | |||
3429 | if (likely(pkt_dev)) { | 3418 | if (likely(pkt_dev)) { |
3430 | pktgen_xmit(pkt_dev); | 3419 | pktgen_xmit(pkt_dev); |
3431 | 3420 | ||
@@ -3456,9 +3445,8 @@ static int pktgen_thread_worker(void *arg) | |||
3456 | } | 3445 | } |
3457 | 3446 | ||
3458 | try_to_freeze(); | 3447 | try_to_freeze(); |
3459 | |||
3460 | set_current_state(TASK_INTERRUPTIBLE); | ||
3461 | } | 3448 | } |
3449 | set_current_state(TASK_INTERRUPTIBLE); | ||
3462 | 3450 | ||
3463 | pr_debug("%s stopping all device\n", t->tsk->comm); | 3451 | pr_debug("%s stopping all device\n", t->tsk->comm); |
3464 | pktgen_stop(t); | 3452 | pktgen_stop(t); |
@@ -3485,8 +3473,8 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, | |||
3485 | struct pktgen_dev *p, *pkt_dev = NULL; | 3473 | struct pktgen_dev *p, *pkt_dev = NULL; |
3486 | size_t len = strlen(ifname); | 3474 | size_t len = strlen(ifname); |
3487 | 3475 | ||
3488 | if_lock(t); | 3476 | rcu_read_lock(); |
3489 | list_for_each_entry(p, &t->if_list, list) | 3477 | list_for_each_entry_rcu(p, &t->if_list, list) |
3490 | if (strncmp(p->odevname, ifname, len) == 0) { | 3478 | if (strncmp(p->odevname, ifname, len) == 0) { |
3491 | if (p->odevname[len]) { | 3479 | if (p->odevname[len]) { |
3492 | if (exact || p->odevname[len] != '@') | 3480 | if (exact || p->odevname[len] != '@') |
@@ -3496,7 +3484,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, | |||
3496 | break; | 3484 | break; |
3497 | } | 3485 | } |
3498 | 3486 | ||
3499 | if_unlock(t); | 3487 | rcu_read_unlock(); |
3500 | pr_debug("find_dev(%s) returning %p\n", ifname, pkt_dev); | 3488 | pr_debug("find_dev(%s) returning %p\n", ifname, pkt_dev); |
3501 | return pkt_dev; | 3489 | return pkt_dev; |
3502 | } | 3490 | } |
@@ -3510,6 +3498,12 @@ static int add_dev_to_thread(struct pktgen_thread *t, | |||
3510 | { | 3498 | { |
3511 | int rv = 0; | 3499 | int rv = 0; |
3512 | 3500 | ||
3501 | /* This function cannot be called concurrently, as its called | ||
3502 | * under pktgen_thread_lock mutex, but it can run from | ||
3503 | * userspace on another CPU than the kthread. The if_lock() | ||
3504 | * is used here to sync with concurrent instances of | ||
3505 | * _rem_dev_from_if_list() invoked via kthread, which is also | ||
3506 | * updating the if_list */ | ||
3513 | if_lock(t); | 3507 | if_lock(t); |
3514 | 3508 | ||
3515 | if (pkt_dev->pg_thread) { | 3509 | if (pkt_dev->pg_thread) { |
@@ -3518,9 +3512,9 @@ static int add_dev_to_thread(struct pktgen_thread *t, | |||
3518 | goto out; | 3512 | goto out; |
3519 | } | 3513 | } |
3520 | 3514 | ||
3521 | list_add(&pkt_dev->list, &t->if_list); | ||
3522 | pkt_dev->pg_thread = t; | ||
3523 | pkt_dev->running = 0; | 3515 | pkt_dev->running = 0; |
3516 | pkt_dev->pg_thread = t; | ||
3517 | list_add_rcu(&pkt_dev->list, &t->if_list); | ||
3524 | 3518 | ||
3525 | out: | 3519 | out: |
3526 | if_unlock(t); | 3520 | if_unlock(t); |
@@ -3675,11 +3669,13 @@ static void _rem_dev_from_if_list(struct pktgen_thread *t, | |||
3675 | struct list_head *q, *n; | 3669 | struct list_head *q, *n; |
3676 | struct pktgen_dev *p; | 3670 | struct pktgen_dev *p; |
3677 | 3671 | ||
3672 | if_lock(t); | ||
3678 | list_for_each_safe(q, n, &t->if_list) { | 3673 | list_for_each_safe(q, n, &t->if_list) { |
3679 | p = list_entry(q, struct pktgen_dev, list); | 3674 | p = list_entry(q, struct pktgen_dev, list); |
3680 | if (p == pkt_dev) | 3675 | if (p == pkt_dev) |
3681 | list_del(&p->list); | 3676 | list_del_rcu(&p->list); |
3682 | } | 3677 | } |
3678 | if_unlock(t); | ||
3683 | } | 3679 | } |
3684 | 3680 | ||
3685 | static int pktgen_remove_device(struct pktgen_thread *t, | 3681 | static int pktgen_remove_device(struct pktgen_thread *t, |
@@ -3699,20 +3695,22 @@ static int pktgen_remove_device(struct pktgen_thread *t, | |||
3699 | pkt_dev->odev = NULL; | 3695 | pkt_dev->odev = NULL; |
3700 | } | 3696 | } |
3701 | 3697 | ||
3702 | /* And update the thread if_list */ | 3698 | /* Remove proc before if_list entry, because add_device uses |
3703 | 3699 | * list to determine if interface already exist, avoid race | |
3704 | _rem_dev_from_if_list(t, pkt_dev); | 3700 | * with proc_create_data() */ |
3705 | |||
3706 | if (pkt_dev->entry) | 3701 | if (pkt_dev->entry) |
3707 | proc_remove(pkt_dev->entry); | 3702 | proc_remove(pkt_dev->entry); |
3708 | 3703 | ||
3704 | /* And update the thread if_list */ | ||
3705 | _rem_dev_from_if_list(t, pkt_dev); | ||
3706 | |||
3709 | #ifdef CONFIG_XFRM | 3707 | #ifdef CONFIG_XFRM |
3710 | free_SAs(pkt_dev); | 3708 | free_SAs(pkt_dev); |
3711 | #endif | 3709 | #endif |
3712 | vfree(pkt_dev->flows); | 3710 | vfree(pkt_dev->flows); |
3713 | if (pkt_dev->page) | 3711 | if (pkt_dev->page) |
3714 | put_page(pkt_dev->page); | 3712 | put_page(pkt_dev->page); |
3715 | kfree(pkt_dev); | 3713 | kfree_rcu(pkt_dev, rcu); |
3716 | return 0; | 3714 | return 0; |
3717 | } | 3715 | } |
3718 | 3716 | ||
@@ -3812,6 +3810,7 @@ static void __exit pg_cleanup(void) | |||
3812 | { | 3810 | { |
3813 | unregister_netdevice_notifier(&pktgen_notifier_block); | 3811 | unregister_netdevice_notifier(&pktgen_notifier_block); |
3814 | unregister_pernet_subsys(&pg_net_ops); | 3812 | unregister_pernet_subsys(&pg_net_ops); |
3813 | /* Don't need rcu_barrier() due to use of kfree_rcu() */ | ||
3815 | } | 3814 | } |
3816 | 3815 | ||
3817 | module_init(pg_init); | 3816 | module_init(pg_init); |
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c index d3027a73fd4b..12ab7b4be609 100644 --- a/net/core/ptp_classifier.c +++ b/net/core/ptp_classifier.c | |||
@@ -52,14 +52,43 @@ | |||
52 | * test_8021q: | 52 | * test_8021q: |
53 | * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? | 53 | * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? |
54 | * ldh [16] ; load inner type | 54 | * ldh [16] ; load inner type |
55 | * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? | 55 | * jneq #0x88f7, test_8021q_ipv4 ; ETH_P_1588 ? |
56 | * ldb [18] ; load payload | 56 | * ldb [18] ; load payload |
57 | * and #0x8 ; as we don't have ports here, test | 57 | * and #0x8 ; as we don't have ports here, test |
58 | * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these | 58 | * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these |
59 | * ldh [18] ; reload payload | 59 | * ldh [18] ; reload payload |
60 | * and #0xf ; mask PTP_CLASS_VMASK | 60 | * and #0xf ; mask PTP_CLASS_VMASK |
61 | * or #0x40 ; PTP_CLASS_V2_VLAN | 61 | * or #0x70 ; PTP_CLASS_VLAN|PTP_CLASS_L2 |
62 | * ret a ; return PTP class | ||
63 | * | ||
64 | * ; PTP over UDP over IPv4 over 802.1Q over Ethernet | ||
65 | * test_8021q_ipv4: | ||
66 | * jneq #0x800, test_8021q_ipv6 ; ETH_P_IP ? | ||
67 | * ldb [27] ; load proto | ||
68 | * jneq #17, drop_8021q_ipv4 ; IPPROTO_UDP ? | ||
69 | * ldh [24] ; load frag offset field | ||
70 | * jset #0x1fff, drop_8021q_ipv4; don't allow fragments | ||
71 | * ldxb 4*([18]&0xf) ; load IP header len | ||
72 | * ldh [x + 20] ; load UDP dst port | ||
73 | * jneq #319, drop_8021q_ipv4 ; is port PTP_EV_PORT ? | ||
74 | * ldh [x + 26] ; load payload | ||
75 | * and #0xf ; mask PTP_CLASS_VMASK | ||
76 | * or #0x50 ; PTP_CLASS_VLAN|PTP_CLASS_IPV4 | ||
77 | * ret a ; return PTP class | ||
78 | * drop_8021q_ipv4: ret #0x0 ; PTP_CLASS_NONE | ||
79 | * | ||
80 | * ; PTP over UDP over IPv6 over 802.1Q over Ethernet | ||
81 | * test_8021q_ipv6: | ||
82 | * jneq #0x86dd, drop_8021q_ipv6 ; ETH_P_IPV6 ? | ||
83 | * ldb [24] ; load proto | ||
84 | * jneq #17, drop_8021q_ipv6 ; IPPROTO_UDP ? | ||
85 | * ldh [60] ; load UDP dst port | ||
86 | * jneq #319, drop_8021q_ipv6 ; is port PTP_EV_PORT ? | ||
87 | * ldh [66] ; load payload | ||
88 | * and #0xf ; mask PTP_CLASS_VMASK | ||
89 | * or #0x60 ; PTP_CLASS_VLAN|PTP_CLASS_IPV6 | ||
62 | * ret a ; return PTP class | 90 | * ret a ; return PTP class |
91 | * drop_8021q_ipv6: ret #0x0 ; PTP_CLASS_NONE | ||
63 | * | 92 | * |
64 | * ; PTP over Ethernet | 93 | * ; PTP over Ethernet |
65 | * test_ieee1588: | 94 | * test_ieee1588: |
@@ -113,16 +142,39 @@ void __init ptp_classifier_init(void) | |||
113 | { 0x44, 0, 0, 0x00000020 }, | 142 | { 0x44, 0, 0, 0x00000020 }, |
114 | { 0x16, 0, 0, 0x00000000 }, | 143 | { 0x16, 0, 0, 0x00000000 }, |
115 | { 0x06, 0, 0, 0x00000000 }, | 144 | { 0x06, 0, 0, 0x00000000 }, |
116 | { 0x15, 0, 9, 0x00008100 }, | 145 | { 0x15, 0, 32, 0x00008100 }, |
117 | { 0x28, 0, 0, 0x00000010 }, | 146 | { 0x28, 0, 0, 0x00000010 }, |
118 | { 0x15, 0, 15, 0x000088f7 }, | 147 | { 0x15, 0, 7, 0x000088f7 }, |
119 | { 0x30, 0, 0, 0x00000012 }, | 148 | { 0x30, 0, 0, 0x00000012 }, |
120 | { 0x54, 0, 0, 0x00000008 }, | 149 | { 0x54, 0, 0, 0x00000008 }, |
121 | { 0x15, 0, 12, 0x00000000 }, | 150 | { 0x15, 0, 35, 0x00000000 }, |
122 | { 0x28, 0, 0, 0x00000012 }, | 151 | { 0x28, 0, 0, 0x00000012 }, |
123 | { 0x54, 0, 0, 0x0000000f }, | 152 | { 0x54, 0, 0, 0x0000000f }, |
124 | { 0x44, 0, 0, 0x00000040 }, | 153 | { 0x44, 0, 0, 0x00000070 }, |
154 | { 0x16, 0, 0, 0x00000000 }, | ||
155 | { 0x15, 0, 12, 0x00000800 }, | ||
156 | { 0x30, 0, 0, 0x0000001b }, | ||
157 | { 0x15, 0, 9, 0x00000011 }, | ||
158 | { 0x28, 0, 0, 0x00000018 }, | ||
159 | { 0x45, 7, 0, 0x00001fff }, | ||
160 | { 0xb1, 0, 0, 0x00000012 }, | ||
161 | { 0x48, 0, 0, 0x00000014 }, | ||
162 | { 0x15, 0, 4, 0x0000013f }, | ||
163 | { 0x48, 0, 0, 0x0000001a }, | ||
164 | { 0x54, 0, 0, 0x0000000f }, | ||
165 | { 0x44, 0, 0, 0x00000050 }, | ||
166 | { 0x16, 0, 0, 0x00000000 }, | ||
167 | { 0x06, 0, 0, 0x00000000 }, | ||
168 | { 0x15, 0, 8, 0x000086dd }, | ||
169 | { 0x30, 0, 0, 0x00000018 }, | ||
170 | { 0x15, 0, 6, 0x00000011 }, | ||
171 | { 0x28, 0, 0, 0x0000003c }, | ||
172 | { 0x15, 0, 4, 0x0000013f }, | ||
173 | { 0x28, 0, 0, 0x00000042 }, | ||
174 | { 0x54, 0, 0, 0x0000000f }, | ||
175 | { 0x44, 0, 0, 0x00000060 }, | ||
125 | { 0x16, 0, 0, 0x00000000 }, | 176 | { 0x16, 0, 0, 0x00000000 }, |
177 | { 0x06, 0, 0, 0x00000000 }, | ||
126 | { 0x15, 0, 7, 0x000088f7 }, | 178 | { 0x15, 0, 7, 0x000088f7 }, |
127 | { 0x30, 0, 0, 0x0000000e }, | 179 | { 0x30, 0, 0, 0x0000000e }, |
128 | { 0x54, 0, 0, 0x00000008 }, | 180 | { 0x54, 0, 0, 0x00000008 }, |
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 467f326126e0..04db318e6218 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
@@ -41,27 +41,27 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, | |||
41 | unsigned int nr_table_entries) | 41 | unsigned int nr_table_entries) |
42 | { | 42 | { |
43 | size_t lopt_size = sizeof(struct listen_sock); | 43 | size_t lopt_size = sizeof(struct listen_sock); |
44 | struct listen_sock *lopt; | 44 | struct listen_sock *lopt = NULL; |
45 | 45 | ||
46 | nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); | 46 | nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); |
47 | nr_table_entries = max_t(u32, nr_table_entries, 8); | 47 | nr_table_entries = max_t(u32, nr_table_entries, 8); |
48 | nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); | 48 | nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); |
49 | lopt_size += nr_table_entries * sizeof(struct request_sock *); | 49 | lopt_size += nr_table_entries * sizeof(struct request_sock *); |
50 | if (lopt_size > PAGE_SIZE) | 50 | |
51 | if (lopt_size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) | ||
52 | lopt = kzalloc(lopt_size, GFP_KERNEL | | ||
53 | __GFP_NOWARN | | ||
54 | __GFP_NORETRY); | ||
55 | if (!lopt) | ||
51 | lopt = vzalloc(lopt_size); | 56 | lopt = vzalloc(lopt_size); |
52 | else | 57 | if (!lopt) |
53 | lopt = kzalloc(lopt_size, GFP_KERNEL); | ||
54 | if (lopt == NULL) | ||
55 | return -ENOMEM; | 58 | return -ENOMEM; |
56 | 59 | ||
57 | for (lopt->max_qlen_log = 3; | ||
58 | (1 << lopt->max_qlen_log) < nr_table_entries; | ||
59 | lopt->max_qlen_log++); | ||
60 | |||
61 | get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); | 60 | get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); |
62 | rwlock_init(&queue->syn_wait_lock); | 61 | rwlock_init(&queue->syn_wait_lock); |
63 | queue->rskq_accept_head = NULL; | 62 | queue->rskq_accept_head = NULL; |
64 | lopt->nr_table_entries = nr_table_entries; | 63 | lopt->nr_table_entries = nr_table_entries; |
64 | lopt->max_qlen_log = ilog2(nr_table_entries); | ||
65 | 65 | ||
66 | write_lock_bh(&queue->syn_wait_lock); | 66 | write_lock_bh(&queue->syn_wait_lock); |
67 | queue->listen_opt = lopt; | 67 | queue->listen_opt = lopt; |
@@ -72,22 +72,8 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, | |||
72 | 72 | ||
73 | void __reqsk_queue_destroy(struct request_sock_queue *queue) | 73 | void __reqsk_queue_destroy(struct request_sock_queue *queue) |
74 | { | 74 | { |
75 | struct listen_sock *lopt; | 75 | /* This is an error recovery path only, no locking needed */ |
76 | size_t lopt_size; | 76 | kvfree(queue->listen_opt); |
77 | |||
78 | /* | ||
79 | * this is an error recovery path only | ||
80 | * no locking needed and the lopt is not NULL | ||
81 | */ | ||
82 | |||
83 | lopt = queue->listen_opt; | ||
84 | lopt_size = sizeof(struct listen_sock) + | ||
85 | lopt->nr_table_entries * sizeof(struct request_sock *); | ||
86 | |||
87 | if (lopt_size > PAGE_SIZE) | ||
88 | vfree(lopt); | ||
89 | else | ||
90 | kfree(lopt); | ||
91 | } | 77 | } |
92 | 78 | ||
93 | static inline struct listen_sock *reqsk_queue_yank_listen_sk( | 79 | static inline struct listen_sock *reqsk_queue_yank_listen_sk( |
@@ -107,8 +93,6 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) | |||
107 | { | 93 | { |
108 | /* make all the listen_opt local to us */ | 94 | /* make all the listen_opt local to us */ |
109 | struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); | 95 | struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); |
110 | size_t lopt_size = sizeof(struct listen_sock) + | ||
111 | lopt->nr_table_entries * sizeof(struct request_sock *); | ||
112 | 96 | ||
113 | if (lopt->qlen != 0) { | 97 | if (lopt->qlen != 0) { |
114 | unsigned int i; | 98 | unsigned int i; |
@@ -125,10 +109,7 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) | |||
125 | } | 109 | } |
126 | 110 | ||
127 | WARN_ON(lopt->qlen != 0); | 111 | WARN_ON(lopt->qlen != 0); |
128 | if (lopt_size > PAGE_SIZE) | 112 | kvfree(lopt); |
129 | vfree(lopt); | ||
130 | else | ||
131 | kfree(lopt); | ||
132 | } | 113 | } |
133 | 114 | ||
134 | /* | 115 | /* |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1063996f8317..e9918020dbc9 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -299,7 +299,12 @@ int __rtnl_link_register(struct rtnl_link_ops *ops) | |||
299 | if (rtnl_link_ops_get(ops->kind)) | 299 | if (rtnl_link_ops_get(ops->kind)) |
300 | return -EEXIST; | 300 | return -EEXIST; |
301 | 301 | ||
302 | if (!ops->dellink) | 302 | /* The check for setup is here because if ops |
303 | * does not have that filled up, it is not possible | ||
304 | * to use the ops for creating device. So do not | ||
305 | * fill up dellink as well. That disables rtnl_dellink. | ||
306 | */ | ||
307 | if (ops->setup && !ops->dellink) | ||
303 | ops->dellink = unregister_netdevice_queue; | 308 | ops->dellink = unregister_netdevice_queue; |
304 | 309 | ||
305 | list_add_tail(&ops->list, &link_ops); | 310 | list_add_tail(&ops->list, &link_ops); |
@@ -1777,7 +1782,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1777 | return -ENODEV; | 1782 | return -ENODEV; |
1778 | 1783 | ||
1779 | ops = dev->rtnl_link_ops; | 1784 | ops = dev->rtnl_link_ops; |
1780 | if (!ops) | 1785 | if (!ops || !ops->dellink) |
1781 | return -EOPNOTSUPP; | 1786 | return -EOPNOTSUPP; |
1782 | 1787 | ||
1783 | ops->dellink(dev, &list_kill); | 1788 | ops->dellink(dev, &list_kill); |
@@ -1805,7 +1810,8 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) | |||
1805 | EXPORT_SYMBOL(rtnl_configure_link); | 1810 | EXPORT_SYMBOL(rtnl_configure_link); |
1806 | 1811 | ||
1807 | struct net_device *rtnl_create_link(struct net *net, | 1812 | struct net_device *rtnl_create_link(struct net *net, |
1808 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) | 1813 | char *ifname, unsigned char name_assign_type, |
1814 | const struct rtnl_link_ops *ops, struct nlattr *tb[]) | ||
1809 | { | 1815 | { |
1810 | int err; | 1816 | int err; |
1811 | struct net_device *dev; | 1817 | struct net_device *dev; |
@@ -1823,8 +1829,8 @@ struct net_device *rtnl_create_link(struct net *net, | |||
1823 | num_rx_queues = ops->get_num_rx_queues(); | 1829 | num_rx_queues = ops->get_num_rx_queues(); |
1824 | 1830 | ||
1825 | err = -ENOMEM; | 1831 | err = -ENOMEM; |
1826 | dev = alloc_netdev_mqs(ops->priv_size, ifname, ops->setup, | 1832 | dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, |
1827 | num_tx_queues, num_rx_queues); | 1833 | ops->setup, num_tx_queues, num_rx_queues); |
1828 | if (!dev) | 1834 | if (!dev) |
1829 | goto err; | 1835 | goto err; |
1830 | 1836 | ||
@@ -1889,6 +1895,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1889 | char ifname[IFNAMSIZ]; | 1895 | char ifname[IFNAMSIZ]; |
1890 | struct nlattr *tb[IFLA_MAX+1]; | 1896 | struct nlattr *tb[IFLA_MAX+1]; |
1891 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; | 1897 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; |
1898 | unsigned char name_assign_type = NET_NAME_USER; | ||
1892 | int err; | 1899 | int err; |
1893 | 1900 | ||
1894 | #ifdef CONFIG_MODULES | 1901 | #ifdef CONFIG_MODULES |
@@ -2038,14 +2045,19 @@ replay: | |||
2038 | return -EOPNOTSUPP; | 2045 | return -EOPNOTSUPP; |
2039 | } | 2046 | } |
2040 | 2047 | ||
2041 | if (!ifname[0]) | 2048 | if (!ops->setup) |
2049 | return -EOPNOTSUPP; | ||
2050 | |||
2051 | if (!ifname[0]) { | ||
2042 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 2052 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
2053 | name_assign_type = NET_NAME_ENUM; | ||
2054 | } | ||
2043 | 2055 | ||
2044 | dest_net = rtnl_link_get_net(net, tb); | 2056 | dest_net = rtnl_link_get_net(net, tb); |
2045 | if (IS_ERR(dest_net)) | 2057 | if (IS_ERR(dest_net)) |
2046 | return PTR_ERR(dest_net); | 2058 | return PTR_ERR(dest_net); |
2047 | 2059 | ||
2048 | dev = rtnl_create_link(dest_net, ifname, ops, tb); | 2060 | dev = rtnl_create_link(dest_net, ifname, name_assign_type, ops, tb); |
2049 | if (IS_ERR(dev)) { | 2061 | if (IS_ERR(dev)) { |
2050 | err = PTR_ERR(dev); | 2062 | err = PTR_ERR(dev); |
2051 | goto out; | 2063 | goto out; |
@@ -2509,6 +2521,7 @@ skip: | |||
2509 | int ndo_dflt_fdb_dump(struct sk_buff *skb, | 2521 | int ndo_dflt_fdb_dump(struct sk_buff *skb, |
2510 | struct netlink_callback *cb, | 2522 | struct netlink_callback *cb, |
2511 | struct net_device *dev, | 2523 | struct net_device *dev, |
2524 | struct net_device *filter_dev, | ||
2512 | int idx) | 2525 | int idx) |
2513 | { | 2526 | { |
2514 | int err; | 2527 | int err; |
@@ -2526,28 +2539,72 @@ EXPORT_SYMBOL(ndo_dflt_fdb_dump); | |||
2526 | 2539 | ||
2527 | static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | 2540 | static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) |
2528 | { | 2541 | { |
2529 | int idx = 0; | ||
2530 | struct net *net = sock_net(skb->sk); | ||
2531 | struct net_device *dev; | 2542 | struct net_device *dev; |
2543 | struct nlattr *tb[IFLA_MAX+1]; | ||
2544 | struct net_device *bdev = NULL; | ||
2545 | struct net_device *br_dev = NULL; | ||
2546 | const struct net_device_ops *ops = NULL; | ||
2547 | const struct net_device_ops *cops = NULL; | ||
2548 | struct ifinfomsg *ifm = nlmsg_data(cb->nlh); | ||
2549 | struct net *net = sock_net(skb->sk); | ||
2550 | int brport_idx = 0; | ||
2551 | int br_idx = 0; | ||
2552 | int idx = 0; | ||
2532 | 2553 | ||
2533 | rcu_read_lock(); | 2554 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, |
2534 | for_each_netdev_rcu(net, dev) { | 2555 | ifla_policy) == 0) { |
2535 | if (dev->priv_flags & IFF_BRIDGE_PORT) { | 2556 | if (tb[IFLA_MASTER]) |
2536 | struct net_device *br_dev; | 2557 | br_idx = nla_get_u32(tb[IFLA_MASTER]); |
2537 | const struct net_device_ops *ops; | 2558 | } |
2538 | 2559 | ||
2539 | br_dev = netdev_master_upper_dev_get(dev); | 2560 | brport_idx = ifm->ifi_index; |
2540 | ops = br_dev->netdev_ops; | 2561 | |
2541 | if (ops->ndo_fdb_dump) | 2562 | if (br_idx) { |
2542 | idx = ops->ndo_fdb_dump(skb, cb, dev, idx); | 2563 | br_dev = __dev_get_by_index(net, br_idx); |
2564 | if (!br_dev) | ||
2565 | return -ENODEV; | ||
2566 | |||
2567 | ops = br_dev->netdev_ops; | ||
2568 | bdev = br_dev; | ||
2569 | } | ||
2570 | |||
2571 | for_each_netdev(net, dev) { | ||
2572 | if (brport_idx && (dev->ifindex != brport_idx)) | ||
2573 | continue; | ||
2574 | |||
2575 | if (!br_idx) { /* user did not specify a specific bridge */ | ||
2576 | if (dev->priv_flags & IFF_BRIDGE_PORT) { | ||
2577 | br_dev = netdev_master_upper_dev_get(dev); | ||
2578 | cops = br_dev->netdev_ops; | ||
2579 | } | ||
2580 | |||
2581 | bdev = dev; | ||
2582 | } else { | ||
2583 | if (dev != br_dev && | ||
2584 | !(dev->priv_flags & IFF_BRIDGE_PORT)) | ||
2585 | continue; | ||
2586 | |||
2587 | if (br_dev != netdev_master_upper_dev_get(dev) && | ||
2588 | !(dev->priv_flags & IFF_EBRIDGE)) | ||
2589 | continue; | ||
2590 | |||
2591 | bdev = br_dev; | ||
2592 | cops = ops; | ||
2593 | } | ||
2594 | |||
2595 | if (dev->priv_flags & IFF_BRIDGE_PORT) { | ||
2596 | if (cops && cops->ndo_fdb_dump) | ||
2597 | idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev, | ||
2598 | idx); | ||
2543 | } | 2599 | } |
2544 | 2600 | ||
2601 | idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx); | ||
2545 | if (dev->netdev_ops->ndo_fdb_dump) | 2602 | if (dev->netdev_ops->ndo_fdb_dump) |
2546 | idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx); | 2603 | idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, bdev, dev, |
2547 | else | 2604 | idx); |
2548 | idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); | 2605 | |
2606 | cops = NULL; | ||
2549 | } | 2607 | } |
2550 | rcu_read_unlock(); | ||
2551 | 2608 | ||
2552 | cb->args[0] = idx; | 2609 | cb->args[0] = idx; |
2553 | return skb->len; | 2610 | return skb->len; |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 6521dfd8b7c8..a8770391ea5b 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
@@ -43,31 +43,22 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
43 | return; | 43 | return; |
44 | 44 | ||
45 | type = classify(skb); | 45 | type = classify(skb); |
46 | if (type == PTP_CLASS_NONE) | ||
47 | return; | ||
48 | |||
49 | phydev = skb->dev->phydev; | ||
50 | if (likely(phydev->drv->txtstamp)) { | ||
51 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
52 | return; | ||
46 | 53 | ||
47 | switch (type) { | 54 | clone = skb_clone(skb, GFP_ATOMIC); |
48 | case PTP_CLASS_V1_IPV4: | 55 | if (!clone) { |
49 | case PTP_CLASS_V1_IPV6: | 56 | sock_put(sk); |
50 | case PTP_CLASS_V2_IPV4: | 57 | return; |
51 | case PTP_CLASS_V2_IPV6: | ||
52 | case PTP_CLASS_V2_L2: | ||
53 | case PTP_CLASS_V2_VLAN: | ||
54 | phydev = skb->dev->phydev; | ||
55 | if (likely(phydev->drv->txtstamp)) { | ||
56 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
57 | return; | ||
58 | |||
59 | clone = skb_clone(skb, GFP_ATOMIC); | ||
60 | if (!clone) { | ||
61 | sock_put(sk); | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | clone->sk = sk; | ||
66 | phydev->drv->txtstamp(phydev, clone, type); | ||
67 | } | 58 | } |
68 | break; | 59 | |
69 | default: | 60 | clone->sk = sk; |
70 | break; | 61 | phydev->drv->txtstamp(phydev, clone, type); |
71 | } | 62 | } |
72 | } | 63 | } |
73 | EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); | 64 | EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); |
@@ -114,20 +105,12 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb) | |||
114 | 105 | ||
115 | __skb_pull(skb, ETH_HLEN); | 106 | __skb_pull(skb, ETH_HLEN); |
116 | 107 | ||
117 | switch (type) { | 108 | if (type == PTP_CLASS_NONE) |
118 | case PTP_CLASS_V1_IPV4: | 109 | return false; |
119 | case PTP_CLASS_V1_IPV6: | 110 | |
120 | case PTP_CLASS_V2_IPV4: | 111 | phydev = skb->dev->phydev; |
121 | case PTP_CLASS_V2_IPV6: | 112 | if (likely(phydev->drv->rxtstamp)) |
122 | case PTP_CLASS_V2_L2: | 113 | return phydev->drv->rxtstamp(phydev, skb, type); |
123 | case PTP_CLASS_V2_VLAN: | ||
124 | phydev = skb->dev->phydev; | ||
125 | if (likely(phydev->drv->rxtstamp)) | ||
126 | return phydev->drv->rxtstamp(phydev, skb, type); | ||
127 | break; | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | 114 | ||
132 | return false; | 115 | return false; |
133 | } | 116 | } |