diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 30 | ||||
| -rw-r--r-- | net/core/dst.c | 17 | ||||
| -rw-r--r-- | net/core/ethtool.c | 313 | ||||
| -rw-r--r-- | net/core/fib_rules.c | 6 | ||||
| -rw-r--r-- | net/core/flow.c | 2 | ||||
| -rw-r--r-- | net/core/link_watch.c | 2 | ||||
| -rw-r--r-- | net/core/neighbour.c | 191 | ||||
| -rw-r--r-- | net/core/net-sysfs.c | 2 | ||||
| -rw-r--r-- | net/core/net-traces.c | 2 | ||||
| -rw-r--r-- | net/core/net_namespace.c | 1 | ||||
| -rw-r--r-- | net/core/netpoll.c | 13 | ||||
| -rw-r--r-- | net/core/pktgen.c | 8 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 64 | ||||
| -rw-r--r-- | net/core/skbuff.c | 84 | ||||
| -rw-r--r-- | net/core/sock.c | 11 | ||||
| -rw-r--r-- | net/core/timestamping.c | 2 |
16 files changed, 250 insertions, 498 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 9c58c1ec41a9..17d67b579beb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -199,6 +199,11 @@ static struct list_head ptype_all __read_mostly; /* Taps */ | |||
| 199 | DEFINE_RWLOCK(dev_base_lock); | 199 | DEFINE_RWLOCK(dev_base_lock); |
| 200 | EXPORT_SYMBOL(dev_base_lock); | 200 | EXPORT_SYMBOL(dev_base_lock); |
| 201 | 201 | ||
| 202 | static inline void dev_base_seq_inc(struct net *net) | ||
| 203 | { | ||
| 204 | while (++net->dev_base_seq == 0); | ||
| 205 | } | ||
| 206 | |||
| 202 | static inline struct hlist_head *dev_name_hash(struct net *net, const char *name) | 207 | static inline struct hlist_head *dev_name_hash(struct net *net, const char *name) |
| 203 | { | 208 | { |
| 204 | unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ)); | 209 | unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ)); |
| @@ -237,6 +242,9 @@ static int list_netdevice(struct net_device *dev) | |||
| 237 | hlist_add_head_rcu(&dev->index_hlist, | 242 | hlist_add_head_rcu(&dev->index_hlist, |
| 238 | dev_index_hash(net, dev->ifindex)); | 243 | dev_index_hash(net, dev->ifindex)); |
| 239 | write_unlock_bh(&dev_base_lock); | 244 | write_unlock_bh(&dev_base_lock); |
| 245 | |||
| 246 | dev_base_seq_inc(net); | ||
| 247 | |||
| 240 | return 0; | 248 | return 0; |
| 241 | } | 249 | } |
| 242 | 250 | ||
| @@ -253,6 +261,8 @@ static void unlist_netdevice(struct net_device *dev) | |||
| 253 | hlist_del_rcu(&dev->name_hlist); | 261 | hlist_del_rcu(&dev->name_hlist); |
| 254 | hlist_del_rcu(&dev->index_hlist); | 262 | hlist_del_rcu(&dev->index_hlist); |
| 255 | write_unlock_bh(&dev_base_lock); | 263 | write_unlock_bh(&dev_base_lock); |
| 264 | |||
| 265 | dev_base_seq_inc(dev_net(dev)); | ||
| 256 | } | 266 | } |
| 257 | 267 | ||
| 258 | /* | 268 | /* |
| @@ -2532,7 +2542,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) | |||
| 2532 | goto done; | 2542 | goto done; |
| 2533 | 2543 | ||
| 2534 | ip = (const struct iphdr *) (skb->data + nhoff); | 2544 | ip = (const struct iphdr *) (skb->data + nhoff); |
| 2535 | if (ip->frag_off & htons(IP_MF | IP_OFFSET)) | 2545 | if (ip_is_fragment(ip)) |
| 2536 | ip_proto = 0; | 2546 | ip_proto = 0; |
| 2537 | else | 2547 | else |
| 2538 | ip_proto = ip->protocol; | 2548 | ip_proto = ip->protocol; |
| @@ -4487,10 +4497,10 @@ void __dev_set_rx_mode(struct net_device *dev) | |||
| 4487 | */ | 4497 | */ |
| 4488 | if (!netdev_uc_empty(dev) && !dev->uc_promisc) { | 4498 | if (!netdev_uc_empty(dev) && !dev->uc_promisc) { |
| 4489 | __dev_set_promiscuity(dev, 1); | 4499 | __dev_set_promiscuity(dev, 1); |
| 4490 | dev->uc_promisc = 1; | 4500 | dev->uc_promisc = true; |
| 4491 | } else if (netdev_uc_empty(dev) && dev->uc_promisc) { | 4501 | } else if (netdev_uc_empty(dev) && dev->uc_promisc) { |
| 4492 | __dev_set_promiscuity(dev, -1); | 4502 | __dev_set_promiscuity(dev, -1); |
| 4493 | dev->uc_promisc = 0; | 4503 | dev->uc_promisc = false; |
| 4494 | } | 4504 | } |
| 4495 | 4505 | ||
| 4496 | if (ops->ndo_set_multicast_list) | 4506 | if (ops->ndo_set_multicast_list) |
| @@ -5199,7 +5209,7 @@ static void rollback_registered(struct net_device *dev) | |||
| 5199 | list_del(&single); | 5209 | list_del(&single); |
| 5200 | } | 5210 | } |
| 5201 | 5211 | ||
| 5202 | u32 netdev_fix_features(struct net_device *dev, u32 features) | 5212 | static u32 netdev_fix_features(struct net_device *dev, u32 features) |
| 5203 | { | 5213 | { |
| 5204 | /* Fix illegal checksum combinations */ | 5214 | /* Fix illegal checksum combinations */ |
| 5205 | if ((features & NETIF_F_HW_CSUM) && | 5215 | if ((features & NETIF_F_HW_CSUM) && |
| @@ -5258,7 +5268,6 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
| 5258 | 5268 | ||
| 5259 | return features; | 5269 | return features; |
| 5260 | } | 5270 | } |
| 5261 | EXPORT_SYMBOL(netdev_fix_features); | ||
| 5262 | 5271 | ||
| 5263 | int __netdev_update_features(struct net_device *dev) | 5272 | int __netdev_update_features(struct net_device *dev) |
| 5264 | { | 5273 | { |
| @@ -5478,11 +5487,9 @@ int register_netdevice(struct net_device *dev) | |||
| 5478 | dev->features |= NETIF_F_NOCACHE_COPY; | 5487 | dev->features |= NETIF_F_NOCACHE_COPY; |
| 5479 | } | 5488 | } |
| 5480 | 5489 | ||
| 5481 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, | 5490 | /* Make NETIF_F_HIGHDMA inheritable to VLAN devices. |
| 5482 | * vlan_dev_init() will do the dev->features check, so these features | ||
| 5483 | * are enabled only if supported by underlying device. | ||
| 5484 | */ | 5491 | */ |
| 5485 | dev->vlan_features |= (NETIF_F_GRO | NETIF_F_HIGHDMA); | 5492 | dev->vlan_features |= NETIF_F_HIGHDMA; |
| 5486 | 5493 | ||
| 5487 | ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); | 5494 | ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); |
| 5488 | ret = notifier_to_errno(ret); | 5495 | ret = notifier_to_errno(ret); |
| @@ -5867,8 +5874,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
| 5867 | 5874 | ||
| 5868 | dev->gso_max_size = GSO_MAX_SIZE; | 5875 | dev->gso_max_size = GSO_MAX_SIZE; |
| 5869 | 5876 | ||
| 5870 | INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list); | ||
| 5871 | dev->ethtool_ntuple_list.count = 0; | ||
| 5872 | INIT_LIST_HEAD(&dev->napi_list); | 5877 | INIT_LIST_HEAD(&dev->napi_list); |
| 5873 | INIT_LIST_HEAD(&dev->unreg_list); | 5878 | INIT_LIST_HEAD(&dev->unreg_list); |
| 5874 | INIT_LIST_HEAD(&dev->link_watch_list); | 5879 | INIT_LIST_HEAD(&dev->link_watch_list); |
| @@ -5932,9 +5937,6 @@ void free_netdev(struct net_device *dev) | |||
| 5932 | /* Flush device addresses */ | 5937 | /* Flush device addresses */ |
| 5933 | dev_addr_flush(dev); | 5938 | dev_addr_flush(dev); |
| 5934 | 5939 | ||
| 5935 | /* Clear ethtool n-tuple list */ | ||
| 5936 | ethtool_ntuple_flush(dev); | ||
| 5937 | |||
| 5938 | list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) | 5940 | list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) |
| 5939 | netif_napi_del(p); | 5941 | netif_napi_del(p); |
| 5940 | 5942 | ||
diff --git a/net/core/dst.c b/net/core/dst.c index 6135f3671692..14b33baf0733 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
| @@ -171,8 +171,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | |||
| 171 | dst_init_metrics(dst, dst_default_metrics, true); | 171 | dst_init_metrics(dst, dst_default_metrics, true); |
| 172 | dst->expires = 0UL; | 172 | dst->expires = 0UL; |
| 173 | dst->path = dst; | 173 | dst->path = dst; |
| 174 | dst->neighbour = NULL; | 174 | dst->_neighbour = NULL; |
| 175 | dst->hh = NULL; | ||
| 176 | #ifdef CONFIG_XFRM | 175 | #ifdef CONFIG_XFRM |
| 177 | dst->xfrm = NULL; | 176 | dst->xfrm = NULL; |
| 178 | #endif | 177 | #endif |
| @@ -226,21 +225,15 @@ struct dst_entry *dst_destroy(struct dst_entry * dst) | |||
| 226 | { | 225 | { |
| 227 | struct dst_entry *child; | 226 | struct dst_entry *child; |
| 228 | struct neighbour *neigh; | 227 | struct neighbour *neigh; |
| 229 | struct hh_cache *hh; | ||
| 230 | 228 | ||
| 231 | smp_rmb(); | 229 | smp_rmb(); |
| 232 | 230 | ||
| 233 | again: | 231 | again: |
| 234 | neigh = dst->neighbour; | 232 | neigh = dst->_neighbour; |
| 235 | hh = dst->hh; | ||
| 236 | child = dst->child; | 233 | child = dst->child; |
| 237 | 234 | ||
| 238 | dst->hh = NULL; | ||
| 239 | if (hh) | ||
| 240 | hh_cache_put(hh); | ||
| 241 | |||
| 242 | if (neigh) { | 235 | if (neigh) { |
| 243 | dst->neighbour = NULL; | 236 | dst->_neighbour = NULL; |
| 244 | neigh_release(neigh); | 237 | neigh_release(neigh); |
| 245 | } | 238 | } |
| 246 | 239 | ||
| @@ -370,8 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
| 370 | dst->dev = dev_net(dst->dev)->loopback_dev; | 363 | dst->dev = dev_net(dst->dev)->loopback_dev; |
| 371 | dev_hold(dst->dev); | 364 | dev_hold(dst->dev); |
| 372 | dev_put(dev); | 365 | dev_put(dev); |
| 373 | if (dst->neighbour && dst->neighbour->dev == dev) { | 366 | if (dst->_neighbour && dst->_neighbour->dev == dev) { |
| 374 | dst->neighbour->dev = dst->dev; | 367 | dst->_neighbour->dev = dst->dev; |
| 375 | dev_hold(dst->dev); | 368 | dev_hold(dst->dev); |
| 376 | dev_put(dev); | 369 | dev_put(dev); |
| 377 | } | 370 | } |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index fd14116ad7f0..6cdba5fc2bed 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -169,18 +169,6 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) | |||
| 169 | } | 169 | } |
| 170 | EXPORT_SYMBOL(ethtool_op_set_flags); | 170 | EXPORT_SYMBOL(ethtool_op_set_flags); |
| 171 | 171 | ||
| 172 | void ethtool_ntuple_flush(struct net_device *dev) | ||
| 173 | { | ||
| 174 | struct ethtool_rx_ntuple_flow_spec_container *fsc, *f; | ||
| 175 | |||
| 176 | list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) { | ||
| 177 | list_del(&fsc->list); | ||
| 178 | kfree(fsc); | ||
| 179 | } | ||
| 180 | dev->ethtool_ntuple_list.count = 0; | ||
| 181 | } | ||
| 182 | EXPORT_SYMBOL(ethtool_ntuple_flush); | ||
| 183 | |||
| 184 | /* Handlers for each ethtool command */ | 172 | /* Handlers for each ethtool command */ |
| 185 | 173 | ||
| 186 | #define ETHTOOL_DEV_FEATURE_WORDS 1 | 174 | #define ETHTOOL_DEV_FEATURE_WORDS 1 |
| @@ -865,34 +853,6 @@ out: | |||
| 865 | return ret; | 853 | return ret; |
| 866 | } | 854 | } |
| 867 | 855 | ||
| 868 | static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | ||
| 869 | struct ethtool_rx_ntuple_flow_spec *spec, | ||
| 870 | struct ethtool_rx_ntuple_flow_spec_container *fsc) | ||
| 871 | { | ||
| 872 | |||
| 873 | /* don't add filters forever */ | ||
| 874 | if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) { | ||
| 875 | /* free the container */ | ||
| 876 | kfree(fsc); | ||
| 877 | return; | ||
| 878 | } | ||
| 879 | |||
| 880 | /* Copy the whole filter over */ | ||
| 881 | fsc->fs.flow_type = spec->flow_type; | ||
| 882 | memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u)); | ||
| 883 | memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u)); | ||
| 884 | |||
| 885 | fsc->fs.vlan_tag = spec->vlan_tag; | ||
| 886 | fsc->fs.vlan_tag_mask = spec->vlan_tag_mask; | ||
| 887 | fsc->fs.data = spec->data; | ||
| 888 | fsc->fs.data_mask = spec->data_mask; | ||
| 889 | fsc->fs.action = spec->action; | ||
| 890 | |||
| 891 | /* add to the list */ | ||
| 892 | list_add_tail_rcu(&fsc->list, &list->list); | ||
| 893 | list->count++; | ||
| 894 | } | ||
| 895 | |||
| 896 | /* | 856 | /* |
| 897 | * ethtool does not (or did not) set masks for flow parameters that are | 857 | * ethtool does not (or did not) set masks for flow parameters that are |
| 898 | * not specified, so if both value and mask are 0 then this must be | 858 | * not specified, so if both value and mask are 0 then this must be |
| @@ -930,8 +890,6 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, | |||
| 930 | { | 890 | { |
| 931 | struct ethtool_rx_ntuple cmd; | 891 | struct ethtool_rx_ntuple cmd; |
| 932 | const struct ethtool_ops *ops = dev->ethtool_ops; | 892 | const struct ethtool_ops *ops = dev->ethtool_ops; |
| 933 | struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; | ||
| 934 | int ret; | ||
| 935 | 893 | ||
| 936 | if (!ops->set_rx_ntuple) | 894 | if (!ops->set_rx_ntuple) |
| 937 | return -EOPNOTSUPP; | 895 | return -EOPNOTSUPP; |
| @@ -944,269 +902,7 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, | |||
| 944 | 902 | ||
| 945 | rx_ntuple_fix_masks(&cmd.fs); | 903 | rx_ntuple_fix_masks(&cmd.fs); |
| 946 | 904 | ||
| 947 | /* | 905 | return ops->set_rx_ntuple(dev, &cmd); |
| 948 | * Cache filter in dev struct for GET operation only if | ||
| 949 | * the underlying driver doesn't have its own GET operation, and | ||
| 950 | * only if the filter was added successfully. First make sure we | ||
| 951 | * can allocate the filter, then continue if successful. | ||
| 952 | */ | ||
| 953 | if (!ops->get_rx_ntuple) { | ||
| 954 | fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); | ||
| 955 | if (!fsc) | ||
| 956 | return -ENOMEM; | ||
| 957 | } | ||
| 958 | |||
| 959 | ret = ops->set_rx_ntuple(dev, &cmd); | ||
| 960 | if (ret) { | ||
| 961 | kfree(fsc); | ||
| 962 | return ret; | ||
| 963 | } | ||
| 964 | |||
| 965 | if (!ops->get_rx_ntuple) | ||
| 966 | __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc); | ||
| 967 | |||
| 968 | return ret; | ||
| 969 | } | ||
| 970 | |||
| 971 | static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) | ||
| 972 | { | ||
| 973 | struct ethtool_gstrings gstrings; | ||
| 974 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
| 975 | struct ethtool_rx_ntuple_flow_spec_container *fsc; | ||
| 976 | u8 *data; | ||
| 977 | char *p; | ||
| 978 | int ret, i, num_strings = 0; | ||
| 979 | |||
| 980 | if (!ops->get_sset_count) | ||
| 981 | return -EOPNOTSUPP; | ||
| 982 | |||
| 983 | if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) | ||
| 984 | return -EFAULT; | ||
| 985 | |||
| 986 | ret = ops->get_sset_count(dev, gstrings.string_set); | ||
| 987 | if (ret < 0) | ||
| 988 | return ret; | ||
| 989 | |||
| 990 | gstrings.len = ret; | ||
| 991 | |||
| 992 | data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); | ||
| 993 | if (!data) | ||
| 994 | return -ENOMEM; | ||
| 995 | |||
| 996 | if (ops->get_rx_ntuple) { | ||
| 997 | /* driver-specific filter grab */ | ||
| 998 | ret = ops->get_rx_ntuple(dev, gstrings.string_set, data); | ||
| 999 | goto copy; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /* default ethtool filter grab */ | ||
| 1003 | i = 0; | ||
| 1004 | p = (char *)data; | ||
| 1005 | list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) { | ||
| 1006 | sprintf(p, "Filter %d:\n", i); | ||
| 1007 | p += ETH_GSTRING_LEN; | ||
| 1008 | num_strings++; | ||
| 1009 | |||
| 1010 | switch (fsc->fs.flow_type) { | ||
| 1011 | case TCP_V4_FLOW: | ||
| 1012 | sprintf(p, "\tFlow Type: TCP\n"); | ||
| 1013 | p += ETH_GSTRING_LEN; | ||
| 1014 | num_strings++; | ||
| 1015 | break; | ||
| 1016 | case UDP_V4_FLOW: | ||
| 1017 | sprintf(p, "\tFlow Type: UDP\n"); | ||
| 1018 | p += ETH_GSTRING_LEN; | ||
| 1019 | num_strings++; | ||
| 1020 | break; | ||
| 1021 | case SCTP_V4_FLOW: | ||
| 1022 | sprintf(p, "\tFlow Type: SCTP\n"); | ||
| 1023 | p += ETH_GSTRING_LEN; | ||
| 1024 | num_strings++; | ||
| 1025 | break; | ||
| 1026 | case AH_ESP_V4_FLOW: | ||
| 1027 | sprintf(p, "\tFlow Type: AH ESP\n"); | ||
| 1028 | p += ETH_GSTRING_LEN; | ||
| 1029 | num_strings++; | ||
| 1030 | break; | ||
| 1031 | case ESP_V4_FLOW: | ||
| 1032 | sprintf(p, "\tFlow Type: ESP\n"); | ||
| 1033 | p += ETH_GSTRING_LEN; | ||
| 1034 | num_strings++; | ||
| 1035 | break; | ||
| 1036 | case IP_USER_FLOW: | ||
| 1037 | sprintf(p, "\tFlow Type: Raw IP\n"); | ||
| 1038 | p += ETH_GSTRING_LEN; | ||
| 1039 | num_strings++; | ||
| 1040 | break; | ||
| 1041 | case IPV4_FLOW: | ||
| 1042 | sprintf(p, "\tFlow Type: IPv4\n"); | ||
| 1043 | p += ETH_GSTRING_LEN; | ||
| 1044 | num_strings++; | ||
| 1045 | break; | ||
| 1046 | default: | ||
| 1047 | sprintf(p, "\tFlow Type: Unknown\n"); | ||
| 1048 | p += ETH_GSTRING_LEN; | ||
| 1049 | num_strings++; | ||
| 1050 | goto unknown_filter; | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | /* now the rest of the filters */ | ||
| 1054 | switch (fsc->fs.flow_type) { | ||
| 1055 | case TCP_V4_FLOW: | ||
| 1056 | case UDP_V4_FLOW: | ||
| 1057 | case SCTP_V4_FLOW: | ||
| 1058 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
| 1059 | fsc->fs.h_u.tcp_ip4_spec.ip4src); | ||
| 1060 | p += ETH_GSTRING_LEN; | ||
| 1061 | num_strings++; | ||
| 1062 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
| 1063 | fsc->fs.m_u.tcp_ip4_spec.ip4src); | ||
| 1064 | p += ETH_GSTRING_LEN; | ||
| 1065 | num_strings++; | ||
| 1066 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
| 1067 | fsc->fs.h_u.tcp_ip4_spec.ip4dst); | ||
| 1068 | p += ETH_GSTRING_LEN; | ||
| 1069 | num_strings++; | ||
| 1070 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
| 1071 | fsc->fs.m_u.tcp_ip4_spec.ip4dst); | ||
| 1072 | p += ETH_GSTRING_LEN; | ||
| 1073 | num_strings++; | ||
| 1074 | sprintf(p, "\tSrc Port: %d, mask: 0x%x\n", | ||
| 1075 | fsc->fs.h_u.tcp_ip4_spec.psrc, | ||
| 1076 | fsc->fs.m_u.tcp_ip4_spec.psrc); | ||
| 1077 | p += ETH_GSTRING_LEN; | ||
| 1078 | num_strings++; | ||
| 1079 | sprintf(p, "\tDest Port: %d, mask: 0x%x\n", | ||
| 1080 | fsc->fs.h_u.tcp_ip4_spec.pdst, | ||
| 1081 | fsc->fs.m_u.tcp_ip4_spec.pdst); | ||
| 1082 | p += ETH_GSTRING_LEN; | ||
| 1083 | num_strings++; | ||
| 1084 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | ||
| 1085 | fsc->fs.h_u.tcp_ip4_spec.tos, | ||
| 1086 | fsc->fs.m_u.tcp_ip4_spec.tos); | ||
| 1087 | p += ETH_GSTRING_LEN; | ||
| 1088 | num_strings++; | ||
| 1089 | break; | ||
| 1090 | case AH_ESP_V4_FLOW: | ||
| 1091 | case ESP_V4_FLOW: | ||
| 1092 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
| 1093 | fsc->fs.h_u.ah_ip4_spec.ip4src); | ||
| 1094 | p += ETH_GSTRING_LEN; | ||
| 1095 | num_strings++; | ||
| 1096 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
| 1097 | fsc->fs.m_u.ah_ip4_spec.ip4src); | ||
| 1098 | p += ETH_GSTRING_LEN; | ||
| 1099 | num_strings++; | ||
| 1100 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
| 1101 | fsc->fs.h_u.ah_ip4_spec.ip4dst); | ||
| 1102 | p += ETH_GSTRING_LEN; | ||
| 1103 | num_strings++; | ||
| 1104 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
| 1105 | fsc->fs.m_u.ah_ip4_spec.ip4dst); | ||
| 1106 | p += ETH_GSTRING_LEN; | ||
| 1107 | num_strings++; | ||
| 1108 | sprintf(p, "\tSPI: %d, mask: 0x%x\n", | ||
| 1109 | fsc->fs.h_u.ah_ip4_spec.spi, | ||
| 1110 | fsc->fs.m_u.ah_ip4_spec.spi); | ||
| 1111 | p += ETH_GSTRING_LEN; | ||
| 1112 | num_strings++; | ||
| 1113 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | ||
| 1114 | fsc->fs.h_u.ah_ip4_spec.tos, | ||
| 1115 | fsc->fs.m_u.ah_ip4_spec.tos); | ||
| 1116 | p += ETH_GSTRING_LEN; | ||
| 1117 | num_strings++; | ||
| 1118 | break; | ||
| 1119 | case IP_USER_FLOW: | ||
| 1120 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
| 1121 | fsc->fs.h_u.usr_ip4_spec.ip4src); | ||
| 1122 | p += ETH_GSTRING_LEN; | ||
| 1123 | num_strings++; | ||
| 1124 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
| 1125 | fsc->fs.m_u.usr_ip4_spec.ip4src); | ||
| 1126 | p += ETH_GSTRING_LEN; | ||
| 1127 | num_strings++; | ||
| 1128 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
| 1129 | fsc->fs.h_u.usr_ip4_spec.ip4dst); | ||
| 1130 | p += ETH_GSTRING_LEN; | ||
| 1131 | num_strings++; | ||
| 1132 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
| 1133 | fsc->fs.m_u.usr_ip4_spec.ip4dst); | ||
| 1134 | p += ETH_GSTRING_LEN; | ||
| 1135 | num_strings++; | ||
| 1136 | break; | ||
| 1137 | case IPV4_FLOW: | ||
| 1138 | sprintf(p, "\tSrc IP addr: 0x%x\n", | ||
| 1139 | fsc->fs.h_u.usr_ip4_spec.ip4src); | ||
| 1140 | p += ETH_GSTRING_LEN; | ||
| 1141 | num_strings++; | ||
| 1142 | sprintf(p, "\tSrc IP mask: 0x%x\n", | ||
| 1143 | fsc->fs.m_u.usr_ip4_spec.ip4src); | ||
| 1144 | p += ETH_GSTRING_LEN; | ||
| 1145 | num_strings++; | ||
| 1146 | sprintf(p, "\tDest IP addr: 0x%x\n", | ||
| 1147 | fsc->fs.h_u.usr_ip4_spec.ip4dst); | ||
| 1148 | p += ETH_GSTRING_LEN; | ||
| 1149 | num_strings++; | ||
| 1150 | sprintf(p, "\tDest IP mask: 0x%x\n", | ||
| 1151 | fsc->fs.m_u.usr_ip4_spec.ip4dst); | ||
| 1152 | p += ETH_GSTRING_LEN; | ||
| 1153 | num_strings++; | ||
| 1154 | sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n", | ||
| 1155 | fsc->fs.h_u.usr_ip4_spec.l4_4_bytes, | ||
| 1156 | fsc->fs.m_u.usr_ip4_spec.l4_4_bytes); | ||
| 1157 | p += ETH_GSTRING_LEN; | ||
| 1158 | num_strings++; | ||
| 1159 | sprintf(p, "\tTOS: %d, mask: 0x%x\n", | ||
| 1160 | fsc->fs.h_u.usr_ip4_spec.tos, | ||
| 1161 | fsc->fs.m_u.usr_ip4_spec.tos); | ||
| 1162 | p += ETH_GSTRING_LEN; | ||
| 1163 | num_strings++; | ||
| 1164 | sprintf(p, "\tIP Version: %d, mask: 0x%x\n", | ||
| 1165 | fsc->fs.h_u.usr_ip4_spec.ip_ver, | ||
| 1166 | fsc->fs.m_u.usr_ip4_spec.ip_ver); | ||
| 1167 | p += ETH_GSTRING_LEN; | ||
| 1168 | num_strings++; | ||
| 1169 | sprintf(p, "\tProtocol: %d, mask: 0x%x\n", | ||
| 1170 | fsc->fs.h_u.usr_ip4_spec.proto, | ||
| 1171 | fsc->fs.m_u.usr_ip4_spec.proto); | ||
| 1172 | p += ETH_GSTRING_LEN; | ||
| 1173 | num_strings++; | ||
| 1174 | break; | ||
| 1175 | } | ||
| 1176 | sprintf(p, "\tVLAN: %d, mask: 0x%x\n", | ||
| 1177 | fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask); | ||
| 1178 | p += ETH_GSTRING_LEN; | ||
| 1179 | num_strings++; | ||
| 1180 | sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data); | ||
| 1181 | p += ETH_GSTRING_LEN; | ||
| 1182 | num_strings++; | ||
| 1183 | sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask); | ||
| 1184 | p += ETH_GSTRING_LEN; | ||
| 1185 | num_strings++; | ||
| 1186 | if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) | ||
| 1187 | sprintf(p, "\tAction: Drop\n"); | ||
| 1188 | else | ||
| 1189 | sprintf(p, "\tAction: Direct to queue %d\n", | ||
| 1190 | fsc->fs.action); | ||
| 1191 | p += ETH_GSTRING_LEN; | ||
| 1192 | num_strings++; | ||
| 1193 | unknown_filter: | ||
| 1194 | i++; | ||
| 1195 | } | ||
| 1196 | copy: | ||
| 1197 | /* indicate to userspace how many strings we actually have */ | ||
| 1198 | gstrings.len = num_strings; | ||
| 1199 | ret = -EFAULT; | ||
| 1200 | if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) | ||
| 1201 | goto out; | ||
| 1202 | useraddr += sizeof(gstrings); | ||
| 1203 | if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) | ||
| 1204 | goto out; | ||
| 1205 | ret = 0; | ||
| 1206 | |||
| 1207 | out: | ||
| 1208 | kfree(data); | ||
| 1209 | return ret; | ||
| 1210 | } | 906 | } |
| 1211 | 907 | ||
| 1212 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) | 908 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) |
| @@ -1227,7 +923,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) | |||
| 1227 | regs.len = reglen; | 923 | regs.len = reglen; |
| 1228 | 924 | ||
| 1229 | regbuf = vzalloc(reglen); | 925 | regbuf = vzalloc(reglen); |
| 1230 | if (!regbuf) | 926 | if (reglen && !regbuf) |
| 1231 | return -ENOMEM; | 927 | return -ENOMEM; |
| 1232 | 928 | ||
| 1233 | ops->get_regs(dev, ®s, regbuf); | 929 | ops->get_regs(dev, ®s, regbuf); |
| @@ -1236,7 +932,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) | |||
| 1236 | if (copy_to_user(useraddr, ®s, sizeof(regs))) | 932 | if (copy_to_user(useraddr, ®s, sizeof(regs))) |
| 1237 | goto out; | 933 | goto out; |
| 1238 | useraddr += offsetof(struct ethtool_regs, data); | 934 | useraddr += offsetof(struct ethtool_regs, data); |
| 1239 | if (copy_to_user(useraddr, regbuf, regs.len)) | 935 | if (regbuf && copy_to_user(useraddr, regbuf, regs.len)) |
| 1240 | goto out; | 936 | goto out; |
| 1241 | ret = 0; | 937 | ret = 0; |
| 1242 | 938 | ||
| @@ -2101,9 +1797,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
| 2101 | case ETHTOOL_SRXNTUPLE: | 1797 | case ETHTOOL_SRXNTUPLE: |
| 2102 | rc = ethtool_set_rx_ntuple(dev, useraddr); | 1798 | rc = ethtool_set_rx_ntuple(dev, useraddr); |
| 2103 | break; | 1799 | break; |
| 2104 | case ETHTOOL_GRXNTUPLE: | ||
| 2105 | rc = ethtool_get_rx_ntuple(dev, useraddr); | ||
| 2106 | break; | ||
| 2107 | case ETHTOOL_GSSET_INFO: | 1800 | case ETHTOOL_GSSET_INFO: |
| 2108 | rc = ethtool_get_sset_info(dev, useraddr); | 1801 | rc = ethtool_get_sset_info(dev, useraddr); |
| 2109 | break; | 1802 | break; |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 008dc70b064b..e7ab0c0285b5 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
| @@ -740,9 +740,9 @@ static struct pernet_operations fib_rules_net_ops = { | |||
| 740 | static int __init fib_rules_init(void) | 740 | static int __init fib_rules_init(void) |
| 741 | { | 741 | { |
| 742 | int err; | 742 | int err; |
| 743 | rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL); | 743 | rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL, NULL); |
| 744 | rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL); | 744 | rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL, NULL); |
| 745 | rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule); | 745 | rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule, NULL); |
| 746 | 746 | ||
| 747 | err = register_pernet_subsys(&fib_rules_net_ops); | 747 | err = register_pernet_subsys(&fib_rules_net_ops); |
| 748 | if (err < 0) | 748 | if (err < 0) |
diff --git a/net/core/flow.c b/net/core/flow.c index 990703b8863b..bf32c33cad3b 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/cpumask.h> | 22 | #include <linux/cpumask.h> |
| 23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
| 24 | #include <net/flow.h> | 24 | #include <net/flow.h> |
| 25 | #include <asm/atomic.h> | 25 | #include <linux/atomic.h> |
| 26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
| 27 | 27 | ||
| 28 | struct flow_cache_entry { | 28 | struct flow_cache_entry { |
diff --git a/net/core/link_watch.c b/net/core/link_watch.c index a7b342131869..357bd4ee4baa 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c | |||
| @@ -126,7 +126,7 @@ static void linkwatch_schedule_work(int urgent) | |||
| 126 | return; | 126 | return; |
| 127 | 127 | ||
| 128 | /* It's already running which is good enough. */ | 128 | /* It's already running which is good enough. */ |
| 129 | if (!cancel_delayed_work(&linkwatch_work)) | 129 | if (!__cancel_delayed_work(&linkwatch_work)) |
| 130 | return; | 130 | return; |
| 131 | 131 | ||
| 132 | /* Otherwise we reschedule it again for immediate execution. */ | 132 | /* Otherwise we reschedule it again for immediate execution. */ |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 799f06e03a22..8fab9b0bb203 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops; | |||
| 98 | 98 | ||
| 99 | static DEFINE_RWLOCK(neigh_tbl_lock); | 99 | static DEFINE_RWLOCK(neigh_tbl_lock); |
| 100 | 100 | ||
| 101 | static int neigh_blackhole(struct sk_buff *skb) | 101 | static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb) |
| 102 | { | 102 | { |
| 103 | kfree_skb(skb); | 103 | kfree_skb(skb); |
| 104 | return -ENETDOWN; | 104 | return -ENETDOWN; |
| @@ -137,7 +137,7 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
| 137 | write_lock_bh(&tbl->lock); | 137 | write_lock_bh(&tbl->lock); |
| 138 | nht = rcu_dereference_protected(tbl->nht, | 138 | nht = rcu_dereference_protected(tbl->nht, |
| 139 | lockdep_is_held(&tbl->lock)); | 139 | lockdep_is_held(&tbl->lock)); |
| 140 | for (i = 0; i <= nht->hash_mask; i++) { | 140 | for (i = 0; i < (1 << nht->hash_shift); i++) { |
| 141 | struct neighbour *n; | 141 | struct neighbour *n; |
| 142 | struct neighbour __rcu **np; | 142 | struct neighbour __rcu **np; |
| 143 | 143 | ||
| @@ -210,7 +210,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) | |||
| 210 | nht = rcu_dereference_protected(tbl->nht, | 210 | nht = rcu_dereference_protected(tbl->nht, |
| 211 | lockdep_is_held(&tbl->lock)); | 211 | lockdep_is_held(&tbl->lock)); |
| 212 | 212 | ||
| 213 | for (i = 0; i <= nht->hash_mask; i++) { | 213 | for (i = 0; i < (1 << nht->hash_shift); i++) { |
| 214 | struct neighbour *n; | 214 | struct neighbour *n; |
| 215 | struct neighbour __rcu **np = &nht->hash_buckets[i]; | 215 | struct neighbour __rcu **np = &nht->hash_buckets[i]; |
| 216 | 216 | ||
| @@ -297,6 +297,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl) | |||
| 297 | n->updated = n->used = now; | 297 | n->updated = n->used = now; |
| 298 | n->nud_state = NUD_NONE; | 298 | n->nud_state = NUD_NONE; |
| 299 | n->output = neigh_blackhole; | 299 | n->output = neigh_blackhole; |
| 300 | seqlock_init(&n->hh.hh_lock); | ||
| 300 | n->parms = neigh_parms_clone(&tbl->parms); | 301 | n->parms = neigh_parms_clone(&tbl->parms); |
| 301 | setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n); | 302 | setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n); |
| 302 | 303 | ||
| @@ -312,9 +313,9 @@ out_entries: | |||
| 312 | goto out; | 313 | goto out; |
| 313 | } | 314 | } |
| 314 | 315 | ||
| 315 | static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries) | 316 | static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift) |
| 316 | { | 317 | { |
| 317 | size_t size = entries * sizeof(struct neighbour *); | 318 | size_t size = (1 << shift) * sizeof(struct neighbour *); |
| 318 | struct neigh_hash_table *ret; | 319 | struct neigh_hash_table *ret; |
| 319 | struct neighbour __rcu **buckets; | 320 | struct neighbour __rcu **buckets; |
| 320 | 321 | ||
| @@ -332,8 +333,9 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries) | |||
| 332 | return NULL; | 333 | return NULL; |
| 333 | } | 334 | } |
| 334 | ret->hash_buckets = buckets; | 335 | ret->hash_buckets = buckets; |
| 335 | ret->hash_mask = entries - 1; | 336 | ret->hash_shift = shift; |
| 336 | get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd)); | 337 | get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd)); |
| 338 | ret->hash_rnd |= 1; | ||
| 337 | return ret; | 339 | return ret; |
| 338 | } | 340 | } |
| 339 | 341 | ||
| @@ -342,7 +344,7 @@ static void neigh_hash_free_rcu(struct rcu_head *head) | |||
| 342 | struct neigh_hash_table *nht = container_of(head, | 344 | struct neigh_hash_table *nht = container_of(head, |
| 343 | struct neigh_hash_table, | 345 | struct neigh_hash_table, |
| 344 | rcu); | 346 | rcu); |
| 345 | size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *); | 347 | size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *); |
| 346 | struct neighbour __rcu **buckets = nht->hash_buckets; | 348 | struct neighbour __rcu **buckets = nht->hash_buckets; |
| 347 | 349 | ||
| 348 | if (size <= PAGE_SIZE) | 350 | if (size <= PAGE_SIZE) |
| @@ -353,21 +355,20 @@ static void neigh_hash_free_rcu(struct rcu_head *head) | |||
| 353 | } | 355 | } |
| 354 | 356 | ||
| 355 | static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, | 357 | static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, |
| 356 | unsigned long new_entries) | 358 | unsigned long new_shift) |
| 357 | { | 359 | { |
| 358 | unsigned int i, hash; | 360 | unsigned int i, hash; |
| 359 | struct neigh_hash_table *new_nht, *old_nht; | 361 | struct neigh_hash_table *new_nht, *old_nht; |
| 360 | 362 | ||
| 361 | NEIGH_CACHE_STAT_INC(tbl, hash_grows); | 363 | NEIGH_CACHE_STAT_INC(tbl, hash_grows); |
| 362 | 364 | ||
| 363 | BUG_ON(!is_power_of_2(new_entries)); | ||
| 364 | old_nht = rcu_dereference_protected(tbl->nht, | 365 | old_nht = rcu_dereference_protected(tbl->nht, |
| 365 | lockdep_is_held(&tbl->lock)); | 366 | lockdep_is_held(&tbl->lock)); |
| 366 | new_nht = neigh_hash_alloc(new_entries); | 367 | new_nht = neigh_hash_alloc(new_shift); |
| 367 | if (!new_nht) | 368 | if (!new_nht) |
| 368 | return old_nht; | 369 | return old_nht; |
| 369 | 370 | ||
| 370 | for (i = 0; i <= old_nht->hash_mask; i++) { | 371 | for (i = 0; i < (1 << old_nht->hash_shift); i++) { |
| 371 | struct neighbour *n, *next; | 372 | struct neighbour *n, *next; |
| 372 | 373 | ||
| 373 | for (n = rcu_dereference_protected(old_nht->hash_buckets[i], | 374 | for (n = rcu_dereference_protected(old_nht->hash_buckets[i], |
| @@ -377,7 +378,7 @@ static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, | |||
| 377 | hash = tbl->hash(n->primary_key, n->dev, | 378 | hash = tbl->hash(n->primary_key, n->dev, |
| 378 | new_nht->hash_rnd); | 379 | new_nht->hash_rnd); |
| 379 | 380 | ||
| 380 | hash &= new_nht->hash_mask; | 381 | hash >>= (32 - new_nht->hash_shift); |
| 381 | next = rcu_dereference_protected(n->next, | 382 | next = rcu_dereference_protected(n->next, |
| 382 | lockdep_is_held(&tbl->lock)); | 383 | lockdep_is_held(&tbl->lock)); |
| 383 | 384 | ||
| @@ -406,7 +407,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
| 406 | 407 | ||
| 407 | rcu_read_lock_bh(); | 408 | rcu_read_lock_bh(); |
| 408 | nht = rcu_dereference_bh(tbl->nht); | 409 | nht = rcu_dereference_bh(tbl->nht); |
| 409 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask; | 410 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); |
| 410 | 411 | ||
| 411 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | 412 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); |
| 412 | n != NULL; | 413 | n != NULL; |
| @@ -436,7 +437,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, | |||
| 436 | 437 | ||
| 437 | rcu_read_lock_bh(); | 438 | rcu_read_lock_bh(); |
| 438 | nht = rcu_dereference_bh(tbl->nht); | 439 | nht = rcu_dereference_bh(tbl->nht); |
| 439 | hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) & nht->hash_mask; | 440 | hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift); |
| 440 | 441 | ||
| 441 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | 442 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); |
| 442 | n != NULL; | 443 | n != NULL; |
| @@ -492,10 +493,10 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, | |||
| 492 | nht = rcu_dereference_protected(tbl->nht, | 493 | nht = rcu_dereference_protected(tbl->nht, |
| 493 | lockdep_is_held(&tbl->lock)); | 494 | lockdep_is_held(&tbl->lock)); |
| 494 | 495 | ||
| 495 | if (atomic_read(&tbl->entries) > (nht->hash_mask + 1)) | 496 | if (atomic_read(&tbl->entries) > (1 << nht->hash_shift)) |
| 496 | nht = neigh_hash_grow(tbl, (nht->hash_mask + 1) << 1); | 497 | nht = neigh_hash_grow(tbl, nht->hash_shift + 1); |
| 497 | 498 | ||
| 498 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask; | 499 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); |
| 499 | 500 | ||
| 500 | if (n->parms->dead) { | 501 | if (n->parms->dead) { |
| 501 | rc = ERR_PTR(-EINVAL); | 502 | rc = ERR_PTR(-EINVAL); |
| @@ -688,8 +689,6 @@ static void neigh_destroy_rcu(struct rcu_head *head) | |||
| 688 | */ | 689 | */ |
| 689 | void neigh_destroy(struct neighbour *neigh) | 690 | void neigh_destroy(struct neighbour *neigh) |
| 690 | { | 691 | { |
| 691 | struct hh_cache *hh; | ||
| 692 | |||
| 693 | NEIGH_CACHE_STAT_INC(neigh->tbl, destroys); | 692 | NEIGH_CACHE_STAT_INC(neigh->tbl, destroys); |
| 694 | 693 | ||
| 695 | if (!neigh->dead) { | 694 | if (!neigh->dead) { |
| @@ -702,16 +701,6 @@ void neigh_destroy(struct neighbour *neigh) | |||
| 702 | if (neigh_del_timer(neigh)) | 701 | if (neigh_del_timer(neigh)) |
| 703 | printk(KERN_WARNING "Impossible event.\n"); | 702 | printk(KERN_WARNING "Impossible event.\n"); |
| 704 | 703 | ||
| 705 | while ((hh = neigh->hh) != NULL) { | ||
| 706 | neigh->hh = hh->hh_next; | ||
| 707 | hh->hh_next = NULL; | ||
| 708 | |||
| 709 | write_seqlock_bh(&hh->hh_lock); | ||
| 710 | hh->hh_output = neigh_blackhole; | ||
| 711 | write_sequnlock_bh(&hh->hh_lock); | ||
| 712 | hh_cache_put(hh); | ||
| 713 | } | ||
| 714 | |||
| 715 | skb_queue_purge(&neigh->arp_queue); | 704 | skb_queue_purge(&neigh->arp_queue); |
| 716 | 705 | ||
| 717 | dev_put(neigh->dev); | 706 | dev_put(neigh->dev); |
| @@ -731,14 +720,9 @@ EXPORT_SYMBOL(neigh_destroy); | |||
| 731 | */ | 720 | */ |
| 732 | static void neigh_suspect(struct neighbour *neigh) | 721 | static void neigh_suspect(struct neighbour *neigh) |
| 733 | { | 722 | { |
| 734 | struct hh_cache *hh; | ||
| 735 | |||
| 736 | NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); | 723 | NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); |
| 737 | 724 | ||
| 738 | neigh->output = neigh->ops->output; | 725 | neigh->output = neigh->ops->output; |
| 739 | |||
| 740 | for (hh = neigh->hh; hh; hh = hh->hh_next) | ||
| 741 | hh->hh_output = neigh->ops->output; | ||
| 742 | } | 726 | } |
| 743 | 727 | ||
| 744 | /* Neighbour state is OK; | 728 | /* Neighbour state is OK; |
| @@ -748,14 +732,9 @@ static void neigh_suspect(struct neighbour *neigh) | |||
| 748 | */ | 732 | */ |
| 749 | static void neigh_connect(struct neighbour *neigh) | 733 | static void neigh_connect(struct neighbour *neigh) |
| 750 | { | 734 | { |
| 751 | struct hh_cache *hh; | ||
| 752 | |||
| 753 | NEIGH_PRINTK2("neigh %p is connected.\n", neigh); | 735 | NEIGH_PRINTK2("neigh %p is connected.\n", neigh); |
| 754 | 736 | ||
| 755 | neigh->output = neigh->ops->connected_output; | 737 | neigh->output = neigh->ops->connected_output; |
| 756 | |||
| 757 | for (hh = neigh->hh; hh; hh = hh->hh_next) | ||
| 758 | hh->hh_output = neigh->ops->hh_output; | ||
| 759 | } | 738 | } |
| 760 | 739 | ||
| 761 | static void neigh_periodic_work(struct work_struct *work) | 740 | static void neigh_periodic_work(struct work_struct *work) |
| @@ -784,7 +763,7 @@ static void neigh_periodic_work(struct work_struct *work) | |||
| 784 | neigh_rand_reach_time(p->base_reachable_time); | 763 | neigh_rand_reach_time(p->base_reachable_time); |
| 785 | } | 764 | } |
| 786 | 765 | ||
| 787 | for (i = 0 ; i <= nht->hash_mask; i++) { | 766 | for (i = 0 ; i < (1 << nht->hash_shift); i++) { |
| 788 | np = &nht->hash_buckets[i]; | 767 | np = &nht->hash_buckets[i]; |
| 789 | 768 | ||
| 790 | while ((n = rcu_dereference_protected(*np, | 769 | while ((n = rcu_dereference_protected(*np, |
| @@ -1015,7 +994,7 @@ out_unlock_bh: | |||
| 1015 | } | 994 | } |
| 1016 | EXPORT_SYMBOL(__neigh_event_send); | 995 | EXPORT_SYMBOL(__neigh_event_send); |
| 1017 | 996 | ||
| 1018 | static void neigh_update_hhs(const struct neighbour *neigh) | 997 | static void neigh_update_hhs(struct neighbour *neigh) |
| 1019 | { | 998 | { |
| 1020 | struct hh_cache *hh; | 999 | struct hh_cache *hh; |
| 1021 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) | 1000 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) |
| @@ -1025,7 +1004,8 @@ static void neigh_update_hhs(const struct neighbour *neigh) | |||
| 1025 | update = neigh->dev->header_ops->cache_update; | 1004 | update = neigh->dev->header_ops->cache_update; |
| 1026 | 1005 | ||
| 1027 | if (update) { | 1006 | if (update) { |
| 1028 | for (hh = neigh->hh; hh; hh = hh->hh_next) { | 1007 | hh = &neigh->hh; |
| 1008 | if (hh->hh_len) { | ||
| 1029 | write_seqlock_bh(&hh->hh_lock); | 1009 | write_seqlock_bh(&hh->hh_lock); |
| 1030 | update(hh, neigh->dev, neigh->ha); | 1010 | update(hh, neigh->dev, neigh->ha); |
| 1031 | write_sequnlock_bh(&hh->hh_lock); | 1011 | write_sequnlock_bh(&hh->hh_lock); |
| @@ -1173,12 +1153,13 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
| 1173 | 1153 | ||
| 1174 | while (neigh->nud_state & NUD_VALID && | 1154 | while (neigh->nud_state & NUD_VALID && |
| 1175 | (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) { | 1155 | (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) { |
| 1176 | struct neighbour *n1 = neigh; | 1156 | struct dst_entry *dst = skb_dst(skb); |
| 1157 | struct neighbour *n2, *n1 = neigh; | ||
| 1177 | write_unlock_bh(&neigh->lock); | 1158 | write_unlock_bh(&neigh->lock); |
| 1178 | /* On shaper/eql skb->dst->neighbour != neigh :( */ | 1159 | /* On shaper/eql skb->dst->neighbour != neigh :( */ |
| 1179 | if (skb_dst(skb) && skb_dst(skb)->neighbour) | 1160 | if (dst && (n2 = dst_get_neighbour(dst)) != NULL) |
| 1180 | n1 = skb_dst(skb)->neighbour; | 1161 | n1 = n2; |
| 1181 | n1->output(skb); | 1162 | n1->output(n1, skb); |
| 1182 | write_lock_bh(&neigh->lock); | 1163 | write_lock_bh(&neigh->lock); |
| 1183 | } | 1164 | } |
| 1184 | skb_queue_purge(&neigh->arp_queue); | 1165 | skb_queue_purge(&neigh->arp_queue); |
| @@ -1211,67 +1192,21 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, | |||
| 1211 | } | 1192 | } |
| 1212 | EXPORT_SYMBOL(neigh_event_ns); | 1193 | EXPORT_SYMBOL(neigh_event_ns); |
| 1213 | 1194 | ||
| 1214 | static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst, | ||
| 1215 | __be16 protocol) | ||
| 1216 | { | ||
| 1217 | struct hh_cache *hh; | ||
| 1218 | |||
| 1219 | smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */ | ||
| 1220 | for (hh = n->hh; hh; hh = hh->hh_next) { | ||
| 1221 | if (hh->hh_type == protocol) { | ||
| 1222 | atomic_inc(&hh->hh_refcnt); | ||
| 1223 | if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) | ||
| 1224 | hh_cache_put(hh); | ||
| 1225 | return true; | ||
| 1226 | } | ||
| 1227 | } | ||
| 1228 | return false; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | /* called with read_lock_bh(&n->lock); */ | 1195 | /* called with read_lock_bh(&n->lock); */ |
| 1232 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, | 1196 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst) |
| 1233 | __be16 protocol) | ||
| 1234 | { | 1197 | { |
| 1235 | struct hh_cache *hh; | ||
| 1236 | struct net_device *dev = dst->dev; | 1198 | struct net_device *dev = dst->dev; |
| 1237 | 1199 | __be16 prot = dst->ops->protocol; | |
| 1238 | if (likely(neigh_hh_lookup(n, dst, protocol))) | 1200 | struct hh_cache *hh = &n->hh; |
| 1239 | return; | ||
| 1240 | |||
| 1241 | /* slow path */ | ||
| 1242 | hh = kzalloc(sizeof(*hh), GFP_ATOMIC); | ||
| 1243 | if (!hh) | ||
| 1244 | return; | ||
| 1245 | |||
| 1246 | seqlock_init(&hh->hh_lock); | ||
| 1247 | hh->hh_type = protocol; | ||
| 1248 | atomic_set(&hh->hh_refcnt, 2); | ||
| 1249 | |||
| 1250 | if (dev->header_ops->cache(n, hh)) { | ||
| 1251 | kfree(hh); | ||
| 1252 | return; | ||
| 1253 | } | ||
| 1254 | 1201 | ||
| 1255 | write_lock_bh(&n->lock); | 1202 | write_lock_bh(&n->lock); |
| 1256 | 1203 | ||
| 1257 | /* must check if another thread already did the insert */ | 1204 | /* Only one thread can come in here and initialize the |
| 1258 | if (neigh_hh_lookup(n, dst, protocol)) { | 1205 | * hh_cache entry. |
| 1259 | kfree(hh); | 1206 | */ |
| 1260 | goto end; | 1207 | if (!hh->hh_len) |
| 1261 | } | 1208 | dev->header_ops->cache(n, hh, prot); |
| 1262 | |||
| 1263 | if (n->nud_state & NUD_CONNECTED) | ||
| 1264 | hh->hh_output = n->ops->hh_output; | ||
| 1265 | else | ||
| 1266 | hh->hh_output = n->ops->output; | ||
| 1267 | |||
| 1268 | hh->hh_next = n->hh; | ||
| 1269 | smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */ | ||
| 1270 | n->hh = hh; | ||
| 1271 | 1209 | ||
| 1272 | if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) | ||
| 1273 | hh_cache_put(hh); | ||
| 1274 | end: | ||
| 1275 | write_unlock_bh(&n->lock); | 1210 | write_unlock_bh(&n->lock); |
| 1276 | } | 1211 | } |
| 1277 | 1212 | ||
| @@ -1280,7 +1215,7 @@ end: | |||
| 1280 | * but resolution is not made yet. | 1215 | * but resolution is not made yet. |
| 1281 | */ | 1216 | */ |
| 1282 | 1217 | ||
| 1283 | int neigh_compat_output(struct sk_buff *skb) | 1218 | int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb) |
| 1284 | { | 1219 | { |
| 1285 | struct net_device *dev = skb->dev; | 1220 | struct net_device *dev = skb->dev; |
| 1286 | 1221 | ||
| @@ -1297,13 +1232,12 @@ EXPORT_SYMBOL(neigh_compat_output); | |||
| 1297 | 1232 | ||
| 1298 | /* Slow and careful. */ | 1233 | /* Slow and careful. */ |
| 1299 | 1234 | ||
| 1300 | int neigh_resolve_output(struct sk_buff *skb) | 1235 | int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) |
| 1301 | { | 1236 | { |
| 1302 | struct dst_entry *dst = skb_dst(skb); | 1237 | struct dst_entry *dst = skb_dst(skb); |
| 1303 | struct neighbour *neigh; | ||
| 1304 | int rc = 0; | 1238 | int rc = 0; |
| 1305 | 1239 | ||
| 1306 | if (!dst || !(neigh = dst->neighbour)) | 1240 | if (!dst) |
| 1307 | goto discard; | 1241 | goto discard; |
| 1308 | 1242 | ||
| 1309 | __skb_pull(skb, skb_network_offset(skb)); | 1243 | __skb_pull(skb, skb_network_offset(skb)); |
| @@ -1313,10 +1247,8 @@ int neigh_resolve_output(struct sk_buff *skb) | |||
| 1313 | struct net_device *dev = neigh->dev; | 1247 | struct net_device *dev = neigh->dev; |
| 1314 | unsigned int seq; | 1248 | unsigned int seq; |
| 1315 | 1249 | ||
| 1316 | if (dev->header_ops->cache && | 1250 | if (dev->header_ops->cache && !neigh->hh.hh_len) |
| 1317 | !dst->hh && | 1251 | neigh_hh_init(neigh, dst); |
| 1318 | !(dst->flags & DST_NOCACHE)) | ||
| 1319 | neigh_hh_init(neigh, dst, dst->ops->protocol); | ||
| 1320 | 1252 | ||
| 1321 | do { | 1253 | do { |
| 1322 | seq = read_seqbegin(&neigh->ha_lock); | 1254 | seq = read_seqbegin(&neigh->ha_lock); |
| @@ -1325,7 +1257,7 @@ int neigh_resolve_output(struct sk_buff *skb) | |||
| 1325 | } while (read_seqretry(&neigh->ha_lock, seq)); | 1257 | } while (read_seqretry(&neigh->ha_lock, seq)); |
| 1326 | 1258 | ||
| 1327 | if (err >= 0) | 1259 | if (err >= 0) |
| 1328 | rc = neigh->ops->queue_xmit(skb); | 1260 | rc = dev_queue_xmit(skb); |
| 1329 | else | 1261 | else |
| 1330 | goto out_kfree_skb; | 1262 | goto out_kfree_skb; |
| 1331 | } | 1263 | } |
| @@ -1333,7 +1265,7 @@ out: | |||
| 1333 | return rc; | 1265 | return rc; |
| 1334 | discard: | 1266 | discard: |
| 1335 | NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", | 1267 | NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", |
| 1336 | dst, dst ? dst->neighbour : NULL); | 1268 | dst, neigh); |
| 1337 | out_kfree_skb: | 1269 | out_kfree_skb: |
| 1338 | rc = -EINVAL; | 1270 | rc = -EINVAL; |
| 1339 | kfree_skb(skb); | 1271 | kfree_skb(skb); |
| @@ -1343,13 +1275,11 @@ EXPORT_SYMBOL(neigh_resolve_output); | |||
| 1343 | 1275 | ||
| 1344 | /* As fast as possible without hh cache */ | 1276 | /* As fast as possible without hh cache */ |
| 1345 | 1277 | ||
| 1346 | int neigh_connected_output(struct sk_buff *skb) | 1278 | int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) |
| 1347 | { | 1279 | { |
| 1348 | int err; | ||
| 1349 | struct dst_entry *dst = skb_dst(skb); | ||
| 1350 | struct neighbour *neigh = dst->neighbour; | ||
| 1351 | struct net_device *dev = neigh->dev; | 1280 | struct net_device *dev = neigh->dev; |
| 1352 | unsigned int seq; | 1281 | unsigned int seq; |
| 1282 | int err; | ||
| 1353 | 1283 | ||
| 1354 | __skb_pull(skb, skb_network_offset(skb)); | 1284 | __skb_pull(skb, skb_network_offset(skb)); |
| 1355 | 1285 | ||
| @@ -1360,7 +1290,7 @@ int neigh_connected_output(struct sk_buff *skb) | |||
| 1360 | } while (read_seqretry(&neigh->ha_lock, seq)); | 1290 | } while (read_seqretry(&neigh->ha_lock, seq)); |
| 1361 | 1291 | ||
| 1362 | if (err >= 0) | 1292 | if (err >= 0) |
| 1363 | err = neigh->ops->queue_xmit(skb); | 1293 | err = dev_queue_xmit(skb); |
| 1364 | else { | 1294 | else { |
| 1365 | err = -EINVAL; | 1295 | err = -EINVAL; |
| 1366 | kfree_skb(skb); | 1296 | kfree_skb(skb); |
| @@ -1369,6 +1299,12 @@ int neigh_connected_output(struct sk_buff *skb) | |||
| 1369 | } | 1299 | } |
| 1370 | EXPORT_SYMBOL(neigh_connected_output); | 1300 | EXPORT_SYMBOL(neigh_connected_output); |
| 1371 | 1301 | ||
| 1302 | int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb) | ||
| 1303 | { | ||
| 1304 | return dev_queue_xmit(skb); | ||
| 1305 | } | ||
| 1306 | EXPORT_SYMBOL(neigh_direct_output); | ||
| 1307 | |||
| 1372 | static void neigh_proxy_process(unsigned long arg) | 1308 | static void neigh_proxy_process(unsigned long arg) |
| 1373 | { | 1309 | { |
| 1374 | struct neigh_table *tbl = (struct neigh_table *)arg; | 1310 | struct neigh_table *tbl = (struct neigh_table *)arg; |
| @@ -1540,7 +1476,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
| 1540 | panic("cannot create neighbour proc dir entry"); | 1476 | panic("cannot create neighbour proc dir entry"); |
| 1541 | #endif | 1477 | #endif |
| 1542 | 1478 | ||
| 1543 | RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(8)); | 1479 | RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3)); |
| 1544 | 1480 | ||
| 1545 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); | 1481 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); |
| 1546 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); | 1482 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); |
| @@ -1857,7 +1793,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, | |||
| 1857 | rcu_read_lock_bh(); | 1793 | rcu_read_lock_bh(); |
| 1858 | nht = rcu_dereference_bh(tbl->nht); | 1794 | nht = rcu_dereference_bh(tbl->nht); |
| 1859 | ndc.ndtc_hash_rnd = nht->hash_rnd; | 1795 | ndc.ndtc_hash_rnd = nht->hash_rnd; |
| 1860 | ndc.ndtc_hash_mask = nht->hash_mask; | 1796 | ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1); |
| 1861 | rcu_read_unlock_bh(); | 1797 | rcu_read_unlock_bh(); |
| 1862 | 1798 | ||
| 1863 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); | 1799 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); |
| @@ -2200,7 +2136,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
| 2200 | rcu_read_lock_bh(); | 2136 | rcu_read_lock_bh(); |
| 2201 | nht = rcu_dereference_bh(tbl->nht); | 2137 | nht = rcu_dereference_bh(tbl->nht); |
| 2202 | 2138 | ||
| 2203 | for (h = 0; h <= nht->hash_mask; h++) { | 2139 | for (h = 0; h < (1 << nht->hash_shift); h++) { |
| 2204 | if (h < s_h) | 2140 | if (h < s_h) |
| 2205 | continue; | 2141 | continue; |
| 2206 | if (h > s_h) | 2142 | if (h > s_h) |
| @@ -2264,7 +2200,7 @@ void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void | |||
| 2264 | nht = rcu_dereference_bh(tbl->nht); | 2200 | nht = rcu_dereference_bh(tbl->nht); |
| 2265 | 2201 | ||
| 2266 | read_lock(&tbl->lock); /* avoid resizes */ | 2202 | read_lock(&tbl->lock); /* avoid resizes */ |
| 2267 | for (chain = 0; chain <= nht->hash_mask; chain++) { | 2203 | for (chain = 0; chain < (1 << nht->hash_shift); chain++) { |
| 2268 | struct neighbour *n; | 2204 | struct neighbour *n; |
| 2269 | 2205 | ||
| 2270 | for (n = rcu_dereference_bh(nht->hash_buckets[chain]); | 2206 | for (n = rcu_dereference_bh(nht->hash_buckets[chain]); |
| @@ -2286,7 +2222,7 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
| 2286 | 2222 | ||
| 2287 | nht = rcu_dereference_protected(tbl->nht, | 2223 | nht = rcu_dereference_protected(tbl->nht, |
| 2288 | lockdep_is_held(&tbl->lock)); | 2224 | lockdep_is_held(&tbl->lock)); |
| 2289 | for (chain = 0; chain <= nht->hash_mask; chain++) { | 2225 | for (chain = 0; chain < (1 << nht->hash_shift); chain++) { |
| 2290 | struct neighbour *n; | 2226 | struct neighbour *n; |
| 2291 | struct neighbour __rcu **np; | 2227 | struct neighbour __rcu **np; |
| 2292 | 2228 | ||
| @@ -2323,7 +2259,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) | |||
| 2323 | int bucket = state->bucket; | 2259 | int bucket = state->bucket; |
| 2324 | 2260 | ||
| 2325 | state->flags &= ~NEIGH_SEQ_IS_PNEIGH; | 2261 | state->flags &= ~NEIGH_SEQ_IS_PNEIGH; |
| 2326 | for (bucket = 0; bucket <= nht->hash_mask; bucket++) { | 2262 | for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) { |
| 2327 | n = rcu_dereference_bh(nht->hash_buckets[bucket]); | 2263 | n = rcu_dereference_bh(nht->hash_buckets[bucket]); |
| 2328 | 2264 | ||
| 2329 | while (n) { | 2265 | while (n) { |
| @@ -2390,7 +2326,7 @@ next: | |||
| 2390 | if (n) | 2326 | if (n) |
| 2391 | break; | 2327 | break; |
| 2392 | 2328 | ||
| 2393 | if (++state->bucket > nht->hash_mask) | 2329 | if (++state->bucket >= (1 << nht->hash_shift)) |
| 2394 | break; | 2330 | break; |
| 2395 | 2331 | ||
| 2396 | n = rcu_dereference_bh(nht->hash_buckets[state->bucket]); | 2332 | n = rcu_dereference_bh(nht->hash_buckets[state->bucket]); |
| @@ -2909,12 +2845,13 @@ EXPORT_SYMBOL(neigh_sysctl_unregister); | |||
| 2909 | 2845 | ||
| 2910 | static int __init neigh_init(void) | 2846 | static int __init neigh_init(void) |
| 2911 | { | 2847 | { |
| 2912 | rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL); | 2848 | rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL); |
| 2913 | rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL); | 2849 | rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL); |
| 2914 | rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info); | 2850 | rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL); |
| 2915 | 2851 | ||
| 2916 | rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info); | 2852 | rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info, |
| 2917 | rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL); | 2853 | NULL); |
| 2854 | rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL); | ||
| 2918 | 2855 | ||
| 2919 | return 0; | 2856 | return 0; |
| 2920 | } | 2857 | } |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 33d2a1fba131..1683e5db2f27 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
| @@ -100,7 +100,6 @@ NETDEVICE_SHOW(addr_assign_type, fmt_dec); | |||
| 100 | NETDEVICE_SHOW(addr_len, fmt_dec); | 100 | NETDEVICE_SHOW(addr_len, fmt_dec); |
| 101 | NETDEVICE_SHOW(iflink, fmt_dec); | 101 | NETDEVICE_SHOW(iflink, fmt_dec); |
| 102 | NETDEVICE_SHOW(ifindex, fmt_dec); | 102 | NETDEVICE_SHOW(ifindex, fmt_dec); |
| 103 | NETDEVICE_SHOW(features, fmt_hex); | ||
| 104 | NETDEVICE_SHOW(type, fmt_dec); | 103 | NETDEVICE_SHOW(type, fmt_dec); |
| 105 | NETDEVICE_SHOW(link_mode, fmt_dec); | 104 | NETDEVICE_SHOW(link_mode, fmt_dec); |
| 106 | 105 | ||
| @@ -312,7 +311,6 @@ static struct device_attribute net_class_attributes[] = { | |||
| 312 | __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), | 311 | __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), |
| 313 | __ATTR(iflink, S_IRUGO, show_iflink, NULL), | 312 | __ATTR(iflink, S_IRUGO, show_iflink, NULL), |
| 314 | __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), | 313 | __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), |
| 315 | __ATTR(features, S_IRUGO, show_features, NULL), | ||
| 316 | __ATTR(type, S_IRUGO, show_type, NULL), | 314 | __ATTR(type, S_IRUGO, show_type, NULL), |
| 317 | __ATTR(link_mode, S_IRUGO, show_link_mode, NULL), | 315 | __ATTR(link_mode, S_IRUGO, show_link_mode, NULL), |
| 318 | __ATTR(address, S_IRUGO, show_address, NULL), | 316 | __ATTR(address, S_IRUGO, show_address, NULL), |
diff --git a/net/core/net-traces.c b/net/core/net-traces.c index 7f1bb2aba03b..52380b1d552a 100644 --- a/net/core/net-traces.c +++ b/net/core/net-traces.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include <trace/events/skb.h> | 28 | #include <trace/events/skb.h> |
| 29 | #include <trace/events/net.h> | 29 | #include <trace/events/net.h> |
| 30 | #include <trace/events/napi.h> | 30 | #include <trace/events/napi.h> |
| 31 | #include <trace/events/sock.h> | ||
| 32 | #include <trace/events/udp.h> | ||
| 31 | 33 | ||
| 32 | EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); | 34 | EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); |
| 33 | 35 | ||
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index ea489db1bc23..5bbdbf0d3664 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
| @@ -129,6 +129,7 @@ static __net_init int setup_net(struct net *net) | |||
| 129 | 129 | ||
| 130 | atomic_set(&net->count, 1); | 130 | atomic_set(&net->count, 1); |
| 131 | atomic_set(&net->passive, 1); | 131 | atomic_set(&net->passive, 1); |
| 132 | net->dev_base_seq = 1; | ||
| 132 | 133 | ||
| 133 | #ifdef NETNS_REFCNT_DEBUG | 134 | #ifdef NETNS_REFCNT_DEBUG |
| 134 | atomic_set(&net->use_count, 0); | 135 | atomic_set(&net->use_count, 0); |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 18d9cbda3a39..adf84dd8c7b5 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -177,7 +177,7 @@ static void service_arp_queue(struct netpoll_info *npi) | |||
| 177 | } | 177 | } |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | void netpoll_poll_dev(struct net_device *dev) | 180 | static void netpoll_poll_dev(struct net_device *dev) |
| 181 | { | 181 | { |
| 182 | const struct net_device_ops *ops; | 182 | const struct net_device_ops *ops; |
| 183 | 183 | ||
| @@ -208,13 +208,6 @@ void netpoll_poll_dev(struct net_device *dev) | |||
| 208 | 208 | ||
| 209 | zap_completion_queue(); | 209 | zap_completion_queue(); |
| 210 | } | 210 | } |
| 211 | EXPORT_SYMBOL(netpoll_poll_dev); | ||
| 212 | |||
| 213 | void netpoll_poll(struct netpoll *np) | ||
| 214 | { | ||
| 215 | netpoll_poll_dev(np->dev); | ||
| 216 | } | ||
| 217 | EXPORT_SYMBOL(netpoll_poll); | ||
| 218 | 211 | ||
| 219 | static void refill_skbs(void) | 212 | static void refill_skbs(void) |
| 220 | { | 213 | { |
| @@ -275,7 +268,7 @@ repeat: | |||
| 275 | 268 | ||
| 276 | if (!skb) { | 269 | if (!skb) { |
| 277 | if (++count < 10) { | 270 | if (++count < 10) { |
| 278 | netpoll_poll(np); | 271 | netpoll_poll_dev(np->dev); |
| 279 | goto repeat; | 272 | goto repeat; |
| 280 | } | 273 | } |
| 281 | return NULL; | 274 | return NULL; |
| @@ -336,7 +329,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 336 | } | 329 | } |
| 337 | 330 | ||
| 338 | /* tickle device maybe there is some cleanup */ | 331 | /* tickle device maybe there is some cleanup */ |
| 339 | netpoll_poll(np); | 332 | netpoll_poll_dev(np->dev); |
| 340 | 333 | ||
| 341 | udelay(USEC_PER_POLL); | 334 | udelay(USEC_PER_POLL); |
| 342 | } | 335 | } |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index f76079cd750c..e35a6fbb8110 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -1070,7 +1070,9 @@ static ssize_t pktgen_if_write(struct file *file, | |||
| 1070 | len = num_arg(&user_buffer[i], 10, &value); | 1070 | len = num_arg(&user_buffer[i], 10, &value); |
| 1071 | if (len < 0) | 1071 | if (len < 0) |
| 1072 | return len; | 1072 | return len; |
| 1073 | 1073 | if ((value > 0) && | |
| 1074 | (!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING))) | ||
| 1075 | return -ENOTSUPP; | ||
| 1074 | i += len; | 1076 | i += len; |
| 1075 | pkt_dev->clone_skb = value; | 1077 | pkt_dev->clone_skb = value; |
| 1076 | 1078 | ||
| @@ -3555,7 +3557,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
| 3555 | pkt_dev->min_pkt_size = ETH_ZLEN; | 3557 | pkt_dev->min_pkt_size = ETH_ZLEN; |
| 3556 | pkt_dev->max_pkt_size = ETH_ZLEN; | 3558 | pkt_dev->max_pkt_size = ETH_ZLEN; |
| 3557 | pkt_dev->nfrags = 0; | 3559 | pkt_dev->nfrags = 0; |
| 3558 | pkt_dev->clone_skb = pg_clone_skb_d; | ||
| 3559 | pkt_dev->delay = pg_delay_d; | 3560 | pkt_dev->delay = pg_delay_d; |
| 3560 | pkt_dev->count = pg_count_d; | 3561 | pkt_dev->count = pg_count_d; |
| 3561 | pkt_dev->sofar = 0; | 3562 | pkt_dev->sofar = 0; |
| @@ -3563,7 +3564,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
| 3563 | pkt_dev->udp_src_max = 9; | 3564 | pkt_dev->udp_src_max = 9; |
| 3564 | pkt_dev->udp_dst_min = 9; | 3565 | pkt_dev->udp_dst_min = 9; |
| 3565 | pkt_dev->udp_dst_max = 9; | 3566 | pkt_dev->udp_dst_max = 9; |
| 3566 | |||
| 3567 | pkt_dev->vlan_p = 0; | 3567 | pkt_dev->vlan_p = 0; |
| 3568 | pkt_dev->vlan_cfi = 0; | 3568 | pkt_dev->vlan_cfi = 0; |
| 3569 | pkt_dev->vlan_id = 0xffff; | 3569 | pkt_dev->vlan_id = 0xffff; |
| @@ -3575,6 +3575,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
| 3575 | err = pktgen_setup_dev(pkt_dev, ifname); | 3575 | err = pktgen_setup_dev(pkt_dev, ifname); |
| 3576 | if (err) | 3576 | if (err) |
| 3577 | goto out1; | 3577 | goto out1; |
| 3578 | if (pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING) | ||
| 3579 | pkt_dev->clone_skb = pg_clone_skb_d; | ||
| 3578 | 3580 | ||
| 3579 | pkt_dev->entry = proc_create_data(ifname, 0600, pg_proc_dir, | 3581 | pkt_dev->entry = proc_create_data(ifname, 0600, pg_proc_dir, |
| 3580 | &pktgen_if_fops, pkt_dev); | 3582 | &pktgen_if_fops, pkt_dev); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index abd936d8a716..99d9e953fe39 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -56,9 +56,11 @@ | |||
| 56 | struct rtnl_link { | 56 | struct rtnl_link { |
| 57 | rtnl_doit_func doit; | 57 | rtnl_doit_func doit; |
| 58 | rtnl_dumpit_func dumpit; | 58 | rtnl_dumpit_func dumpit; |
| 59 | rtnl_calcit_func calcit; | ||
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 61 | static DEFINE_MUTEX(rtnl_mutex); | 62 | static DEFINE_MUTEX(rtnl_mutex); |
| 63 | static u16 min_ifinfo_dump_size; | ||
| 62 | 64 | ||
| 63 | void rtnl_lock(void) | 65 | void rtnl_lock(void) |
| 64 | { | 66 | { |
| @@ -144,12 +146,28 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) | |||
| 144 | return tab ? tab[msgindex].dumpit : NULL; | 146 | return tab ? tab[msgindex].dumpit : NULL; |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 149 | static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex) | ||
| 150 | { | ||
| 151 | struct rtnl_link *tab; | ||
| 152 | |||
| 153 | if (protocol <= RTNL_FAMILY_MAX) | ||
| 154 | tab = rtnl_msg_handlers[protocol]; | ||
| 155 | else | ||
| 156 | tab = NULL; | ||
| 157 | |||
| 158 | if (tab == NULL || tab[msgindex].calcit == NULL) | ||
| 159 | tab = rtnl_msg_handlers[PF_UNSPEC]; | ||
| 160 | |||
| 161 | return tab ? tab[msgindex].calcit : NULL; | ||
| 162 | } | ||
| 163 | |||
| 147 | /** | 164 | /** |
| 148 | * __rtnl_register - Register a rtnetlink message type | 165 | * __rtnl_register - Register a rtnetlink message type |
| 149 | * @protocol: Protocol family or PF_UNSPEC | 166 | * @protocol: Protocol family or PF_UNSPEC |
| 150 | * @msgtype: rtnetlink message type | 167 | * @msgtype: rtnetlink message type |
| 151 | * @doit: Function pointer called for each request message | 168 | * @doit: Function pointer called for each request message |
| 152 | * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message | 169 | * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message |
| 170 | * @calcit: Function pointer to calc size of dump message | ||
| 153 | * | 171 | * |
| 154 | * Registers the specified function pointers (at least one of them has | 172 | * Registers the specified function pointers (at least one of them has |
| 155 | * to be non-NULL) to be called whenever a request message for the | 173 | * to be non-NULL) to be called whenever a request message for the |
| @@ -162,7 +180,8 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) | |||
| 162 | * Returns 0 on success or a negative error code. | 180 | * Returns 0 on success or a negative error code. |
| 163 | */ | 181 | */ |
| 164 | int __rtnl_register(int protocol, int msgtype, | 182 | int __rtnl_register(int protocol, int msgtype, |
| 165 | rtnl_doit_func doit, rtnl_dumpit_func dumpit) | 183 | rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
| 184 | rtnl_calcit_func calcit) | ||
| 166 | { | 185 | { |
| 167 | struct rtnl_link *tab; | 186 | struct rtnl_link *tab; |
| 168 | int msgindex; | 187 | int msgindex; |
| @@ -185,6 +204,9 @@ int __rtnl_register(int protocol, int msgtype, | |||
| 185 | if (dumpit) | 204 | if (dumpit) |
| 186 | tab[msgindex].dumpit = dumpit; | 205 | tab[msgindex].dumpit = dumpit; |
| 187 | 206 | ||
| 207 | if (calcit) | ||
| 208 | tab[msgindex].calcit = calcit; | ||
| 209 | |||
| 188 | return 0; | 210 | return 0; |
| 189 | } | 211 | } |
| 190 | EXPORT_SYMBOL_GPL(__rtnl_register); | 212 | EXPORT_SYMBOL_GPL(__rtnl_register); |
| @@ -199,9 +221,10 @@ EXPORT_SYMBOL_GPL(__rtnl_register); | |||
| 199 | * of memory implies no sense in continuing. | 221 | * of memory implies no sense in continuing. |
| 200 | */ | 222 | */ |
| 201 | void rtnl_register(int protocol, int msgtype, | 223 | void rtnl_register(int protocol, int msgtype, |
| 202 | rtnl_doit_func doit, rtnl_dumpit_func dumpit) | 224 | rtnl_doit_func doit, rtnl_dumpit_func dumpit, |
| 225 | rtnl_calcit_func calcit) | ||
| 203 | { | 226 | { |
| 204 | if (__rtnl_register(protocol, msgtype, doit, dumpit) < 0) | 227 | if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0) |
| 205 | panic("Unable to register rtnetlink message handler, " | 228 | panic("Unable to register rtnetlink message handler, " |
| 206 | "protocol = %d, message type = %d\n", | 229 | "protocol = %d, message type = %d\n", |
| 207 | protocol, msgtype); | 230 | protocol, msgtype); |
| @@ -1009,6 +1032,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1009 | s_idx = cb->args[1]; | 1032 | s_idx = cb->args[1]; |
| 1010 | 1033 | ||
| 1011 | rcu_read_lock(); | 1034 | rcu_read_lock(); |
| 1035 | cb->seq = net->dev_base_seq; | ||
| 1036 | |||
| 1012 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | 1037 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
| 1013 | idx = 0; | 1038 | idx = 0; |
| 1014 | head = &net->dev_index_head[h]; | 1039 | head = &net->dev_index_head[h]; |
| @@ -1020,6 +1045,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1020 | cb->nlh->nlmsg_seq, 0, | 1045 | cb->nlh->nlmsg_seq, 0, |
| 1021 | NLM_F_MULTI) <= 0) | 1046 | NLM_F_MULTI) <= 0) |
| 1022 | goto out; | 1047 | goto out; |
| 1048 | |||
| 1049 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
| 1023 | cont: | 1050 | cont: |
| 1024 | idx++; | 1051 | idx++; |
| 1025 | } | 1052 | } |
| @@ -1818,6 +1845,11 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
| 1818 | return err; | 1845 | return err; |
| 1819 | } | 1846 | } |
| 1820 | 1847 | ||
| 1848 | static u16 rtnl_calcit(struct sk_buff *skb) | ||
| 1849 | { | ||
| 1850 | return min_ifinfo_dump_size; | ||
| 1851 | } | ||
| 1852 | |||
| 1821 | static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | 1853 | static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) |
| 1822 | { | 1854 | { |
| 1823 | int idx; | 1855 | int idx; |
| @@ -1847,11 +1879,14 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) | |||
| 1847 | struct net *net = dev_net(dev); | 1879 | struct net *net = dev_net(dev); |
| 1848 | struct sk_buff *skb; | 1880 | struct sk_buff *skb; |
| 1849 | int err = -ENOBUFS; | 1881 | int err = -ENOBUFS; |
| 1882 | size_t if_info_size; | ||
| 1850 | 1883 | ||
| 1851 | skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); | 1884 | skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL); |
| 1852 | if (skb == NULL) | 1885 | if (skb == NULL) |
| 1853 | goto errout; | 1886 | goto errout; |
| 1854 | 1887 | ||
| 1888 | min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size); | ||
| 1889 | |||
| 1855 | err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0); | 1890 | err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0); |
| 1856 | if (err < 0) { | 1891 | if (err < 0) { |
| 1857 | /* -EMSGSIZE implies BUG in if_nlmsg_size() */ | 1892 | /* -EMSGSIZE implies BUG in if_nlmsg_size() */ |
| @@ -1902,14 +1937,20 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 1902 | if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { | 1937 | if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { |
| 1903 | struct sock *rtnl; | 1938 | struct sock *rtnl; |
| 1904 | rtnl_dumpit_func dumpit; | 1939 | rtnl_dumpit_func dumpit; |
| 1940 | rtnl_calcit_func calcit; | ||
| 1941 | u16 min_dump_alloc = 0; | ||
| 1905 | 1942 | ||
| 1906 | dumpit = rtnl_get_dumpit(family, type); | 1943 | dumpit = rtnl_get_dumpit(family, type); |
| 1907 | if (dumpit == NULL) | 1944 | if (dumpit == NULL) |
| 1908 | return -EOPNOTSUPP; | 1945 | return -EOPNOTSUPP; |
| 1946 | calcit = rtnl_get_calcit(family, type); | ||
| 1947 | if (calcit) | ||
| 1948 | min_dump_alloc = calcit(skb); | ||
| 1909 | 1949 | ||
| 1910 | __rtnl_unlock(); | 1950 | __rtnl_unlock(); |
| 1911 | rtnl = net->rtnl; | 1951 | rtnl = net->rtnl; |
| 1912 | err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); | 1952 | err = netlink_dump_start(rtnl, skb, nlh, dumpit, |
| 1953 | NULL, min_dump_alloc); | ||
| 1913 | rtnl_lock(); | 1954 | rtnl_lock(); |
| 1914 | return err; | 1955 | return err; |
| 1915 | } | 1956 | } |
| @@ -2019,12 +2060,13 @@ void __init rtnetlink_init(void) | |||
| 2019 | netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); | 2060 | netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); |
| 2020 | register_netdevice_notifier(&rtnetlink_dev_notifier); | 2061 | register_netdevice_notifier(&rtnetlink_dev_notifier); |
| 2021 | 2062 | ||
| 2022 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo); | 2063 | rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, |
| 2023 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL); | 2064 | rtnl_dump_ifinfo, rtnl_calcit); |
| 2024 | rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL); | 2065 | rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL); |
| 2025 | rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL); | 2066 | rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL); |
| 2067 | rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL); | ||
| 2026 | 2068 | ||
| 2027 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all); | 2069 | rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL); |
| 2028 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); | 2070 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL); |
| 2029 | } | 2071 | } |
| 2030 | 2072 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 46cbd28f40f9..2beda824636e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -329,6 +329,18 @@ static void skb_release_data(struct sk_buff *skb) | |||
| 329 | put_page(skb_shinfo(skb)->frags[i].page); | 329 | put_page(skb_shinfo(skb)->frags[i].page); |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | /* | ||
| 333 | * If skb buf is from userspace, we need to notify the caller | ||
| 334 | * the lower device DMA has done; | ||
| 335 | */ | ||
| 336 | if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { | ||
| 337 | struct ubuf_info *uarg; | ||
| 338 | |||
| 339 | uarg = skb_shinfo(skb)->destructor_arg; | ||
| 340 | if (uarg->callback) | ||
| 341 | uarg->callback(uarg); | ||
| 342 | } | ||
| 343 | |||
| 332 | if (skb_has_frag_list(skb)) | 344 | if (skb_has_frag_list(skb)) |
| 333 | skb_drop_fraglist(skb); | 345 | skb_drop_fraglist(skb); |
| 334 | 346 | ||
| @@ -481,6 +493,9 @@ bool skb_recycle_check(struct sk_buff *skb, int skb_size) | |||
| 481 | if (irqs_disabled()) | 493 | if (irqs_disabled()) |
| 482 | return false; | 494 | return false; |
| 483 | 495 | ||
| 496 | if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) | ||
| 497 | return false; | ||
| 498 | |||
| 484 | if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) | 499 | if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) |
| 485 | return false; | 500 | return false; |
| 486 | 501 | ||
| @@ -596,6 +611,51 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) | |||
| 596 | } | 611 | } |
| 597 | EXPORT_SYMBOL_GPL(skb_morph); | 612 | EXPORT_SYMBOL_GPL(skb_morph); |
| 598 | 613 | ||
| 614 | /* skb frags copy userspace buffers to kernel */ | ||
| 615 | static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) | ||
| 616 | { | ||
| 617 | int i; | ||
| 618 | int num_frags = skb_shinfo(skb)->nr_frags; | ||
| 619 | struct page *page, *head = NULL; | ||
| 620 | struct ubuf_info *uarg = skb_shinfo(skb)->destructor_arg; | ||
| 621 | |||
| 622 | for (i = 0; i < num_frags; i++) { | ||
| 623 | u8 *vaddr; | ||
| 624 | skb_frag_t *f = &skb_shinfo(skb)->frags[i]; | ||
| 625 | |||
| 626 | page = alloc_page(GFP_ATOMIC); | ||
| 627 | if (!page) { | ||
| 628 | while (head) { | ||
| 629 | struct page *next = (struct page *)head->private; | ||
| 630 | put_page(head); | ||
| 631 | head = next; | ||
| 632 | } | ||
| 633 | return -ENOMEM; | ||
| 634 | } | ||
| 635 | vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); | ||
| 636 | memcpy(page_address(page), | ||
| 637 | vaddr + f->page_offset, f->size); | ||
| 638 | kunmap_skb_frag(vaddr); | ||
| 639 | page->private = (unsigned long)head; | ||
| 640 | head = page; | ||
| 641 | } | ||
| 642 | |||
| 643 | /* skb frags release userspace buffers */ | ||
| 644 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) | ||
| 645 | put_page(skb_shinfo(skb)->frags[i].page); | ||
| 646 | |||
| 647 | uarg->callback(uarg); | ||
| 648 | |||
| 649 | /* skb frags point to kernel buffers */ | ||
| 650 | for (i = skb_shinfo(skb)->nr_frags; i > 0; i--) { | ||
| 651 | skb_shinfo(skb)->frags[i - 1].page_offset = 0; | ||
| 652 | skb_shinfo(skb)->frags[i - 1].page = head; | ||
| 653 | head = (struct page *)head->private; | ||
| 654 | } | ||
| 655 | return 0; | ||
| 656 | } | ||
| 657 | |||
| 658 | |||
| 599 | /** | 659 | /** |
| 600 | * skb_clone - duplicate an sk_buff | 660 | * skb_clone - duplicate an sk_buff |
| 601 | * @skb: buffer to clone | 661 | * @skb: buffer to clone |
| @@ -614,6 +674,12 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 614 | { | 674 | { |
| 615 | struct sk_buff *n; | 675 | struct sk_buff *n; |
| 616 | 676 | ||
| 677 | if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { | ||
| 678 | if (skb_copy_ubufs(skb, gfp_mask)) | ||
| 679 | return NULL; | ||
| 680 | skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; | ||
| 681 | } | ||
| 682 | |||
| 617 | n = skb + 1; | 683 | n = skb + 1; |
| 618 | if (skb->fclone == SKB_FCLONE_ORIG && | 684 | if (skb->fclone == SKB_FCLONE_ORIG && |
| 619 | n->fclone == SKB_FCLONE_UNAVAILABLE) { | 685 | n->fclone == SKB_FCLONE_UNAVAILABLE) { |
| @@ -731,6 +797,14 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 731 | if (skb_shinfo(skb)->nr_frags) { | 797 | if (skb_shinfo(skb)->nr_frags) { |
| 732 | int i; | 798 | int i; |
| 733 | 799 | ||
| 800 | if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { | ||
| 801 | if (skb_copy_ubufs(skb, gfp_mask)) { | ||
| 802 | kfree_skb(n); | ||
| 803 | n = NULL; | ||
| 804 | goto out; | ||
| 805 | } | ||
| 806 | skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; | ||
| 807 | } | ||
| 734 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 808 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
| 735 | skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; | 809 | skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; |
| 736 | get_page(skb_shinfo(n)->frags[i].page); | 810 | get_page(skb_shinfo(n)->frags[i].page); |
| @@ -788,7 +862,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
| 788 | fastpath = true; | 862 | fastpath = true; |
| 789 | else { | 863 | else { |
| 790 | int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1; | 864 | int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1; |
| 791 | |||
| 792 | fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta; | 865 | fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta; |
| 793 | } | 866 | } |
| 794 | 867 | ||
| @@ -819,6 +892,12 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
| 819 | if (fastpath) { | 892 | if (fastpath) { |
| 820 | kfree(skb->head); | 893 | kfree(skb->head); |
| 821 | } else { | 894 | } else { |
| 895 | /* copy this zero copy skb frags */ | ||
| 896 | if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { | ||
| 897 | if (skb_copy_ubufs(skb, gfp_mask)) | ||
| 898 | goto nofrags; | ||
| 899 | skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; | ||
| 900 | } | ||
| 822 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) | 901 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) |
| 823 | get_page(skb_shinfo(skb)->frags[i].page); | 902 | get_page(skb_shinfo(skb)->frags[i].page); |
| 824 | 903 | ||
| @@ -853,6 +932,8 @@ adjust_others: | |||
| 853 | atomic_set(&skb_shinfo(skb)->dataref, 1); | 932 | atomic_set(&skb_shinfo(skb)->dataref, 1); |
| 854 | return 0; | 933 | return 0; |
| 855 | 934 | ||
| 935 | nofrags: | ||
| 936 | kfree(data); | ||
| 856 | nodata: | 937 | nodata: |
| 857 | return -ENOMEM; | 938 | return -ENOMEM; |
| 858 | } | 939 | } |
| @@ -1354,6 +1435,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) | |||
| 1354 | } | 1435 | } |
| 1355 | start = end; | 1436 | start = end; |
| 1356 | } | 1437 | } |
| 1438 | |||
| 1357 | if (!len) | 1439 | if (!len) |
| 1358 | return 0; | 1440 | return 0; |
| 1359 | 1441 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 6e819780c232..bc745d00ea4d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -128,6 +128,8 @@ | |||
| 128 | 128 | ||
| 129 | #include <linux/filter.h> | 129 | #include <linux/filter.h> |
| 130 | 130 | ||
| 131 | #include <trace/events/sock.h> | ||
| 132 | |||
| 131 | #ifdef CONFIG_INET | 133 | #ifdef CONFIG_INET |
| 132 | #include <net/tcp.h> | 134 | #include <net/tcp.h> |
| 133 | #endif | 135 | #endif |
| @@ -158,7 +160,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = { | |||
| 158 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , | 160 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , |
| 159 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , | 161 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , |
| 160 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" , | 162 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" , |
| 161 | "sk_lock-AF_MAX" | 163 | "sk_lock-AF_NFC" , "sk_lock-AF_MAX" |
| 162 | }; | 164 | }; |
| 163 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { | 165 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { |
| 164 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , | 166 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , |
| @@ -174,7 +176,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = { | |||
| 174 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , | 176 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , |
| 175 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , | 177 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , |
| 176 | "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" , | 178 | "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" , |
| 177 | "slock-AF_MAX" | 179 | "slock-AF_NFC" , "slock-AF_MAX" |
| 178 | }; | 180 | }; |
| 179 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { | 181 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { |
| 180 | "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , | 182 | "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , |
| @@ -190,7 +192,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = { | |||
| 190 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , | 192 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , |
| 191 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , | 193 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , |
| 192 | "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" , | 194 | "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" , |
| 193 | "clock-AF_MAX" | 195 | "clock-AF_NFC" , "clock-AF_MAX" |
| 194 | }; | 196 | }; |
| 195 | 197 | ||
| 196 | /* | 198 | /* |
| @@ -292,6 +294,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 292 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 294 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
| 293 | (unsigned)sk->sk_rcvbuf) { | 295 | (unsigned)sk->sk_rcvbuf) { |
| 294 | atomic_inc(&sk->sk_drops); | 296 | atomic_inc(&sk->sk_drops); |
| 297 | trace_sock_rcvqueue_full(sk, skb); | ||
| 295 | return -ENOMEM; | 298 | return -ENOMEM; |
| 296 | } | 299 | } |
| 297 | 300 | ||
| @@ -1736,6 +1739,8 @@ suppress_allocation: | |||
| 1736 | return 1; | 1739 | return 1; |
| 1737 | } | 1740 | } |
| 1738 | 1741 | ||
| 1742 | trace_sock_exceed_buf_limit(sk, prot, allocated); | ||
| 1743 | |||
| 1739 | /* Alas. Undo changes. */ | 1744 | /* Alas. Undo changes. */ |
| 1740 | sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; | 1745 | sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; |
| 1741 | atomic_long_sub(amt, prot->memory_allocated); | 1746 | atomic_long_sub(amt, prot->memory_allocated); |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 7e7ca375d431..98a52640e7cd 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
| @@ -68,6 +68,7 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
| 68 | break; | 68 | break; |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
| 71 | EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); | ||
| 71 | 72 | ||
| 72 | void skb_complete_tx_timestamp(struct sk_buff *skb, | 73 | void skb_complete_tx_timestamp(struct sk_buff *skb, |
| 73 | struct skb_shared_hwtstamps *hwtstamps) | 74 | struct skb_shared_hwtstamps *hwtstamps) |
| @@ -121,6 +122,7 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb) | |||
| 121 | 122 | ||
| 122 | return false; | 123 | return false; |
| 123 | } | 124 | } |
| 125 | EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp); | ||
| 124 | 126 | ||
| 125 | void __init skb_timestamping_init(void) | 127 | void __init skb_timestamping_init(void) |
| 126 | { | 128 | { |
