diff options
Diffstat (limited to 'net')
108 files changed, 1424 insertions, 487 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 98a30a5b8664..59555f0f8fc8 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
| @@ -443,7 +443,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
| 443 | case NETDEV_UP: | 443 | case NETDEV_UP: |
| 444 | /* Put all VLANs for this dev in the up state too. */ | 444 | /* Put all VLANs for this dev in the up state too. */ |
| 445 | vlan_group_for_each_dev(grp, i, vlandev) { | 445 | vlan_group_for_each_dev(grp, i, vlandev) { |
| 446 | flgs = vlandev->flags; | 446 | flgs = dev_get_flags(vlandev); |
| 447 | if (flgs & IFF_UP) | 447 | if (flgs & IFF_UP) |
| 448 | continue; | 448 | continue; |
| 449 | 449 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 476709bd068a..c4802f3bd4c5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -1557,7 +1557,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
| 1557 | { | 1557 | { |
| 1558 | BT_DBG("%s %p", hdev->name, hdev); | 1558 | BT_DBG("%s %p", hdev->name, hdev); |
| 1559 | 1559 | ||
| 1560 | if (!hci_dev_test_flag(hdev, HCI_UNREGISTER)) { | 1560 | if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && |
| 1561 | test_bit(HCI_UP, &hdev->flags)) { | ||
| 1561 | /* Execute vendor specific shutdown routine */ | 1562 | /* Execute vendor specific shutdown routine */ |
| 1562 | if (hdev->shutdown) | 1563 | if (hdev->shutdown) |
| 1563 | hdev->shutdown(hdev); | 1564 | hdev->shutdown(hdev); |
| @@ -2853,9 +2854,11 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status, | |||
| 2853 | * state. If we were running both LE and BR/EDR inquiry | 2854 | * state. If we were running both LE and BR/EDR inquiry |
| 2854 | * simultaneously, and BR/EDR inquiry is already | 2855 | * simultaneously, and BR/EDR inquiry is already |
| 2855 | * finished, stop discovery, otherwise BR/EDR inquiry | 2856 | * finished, stop discovery, otherwise BR/EDR inquiry |
| 2856 | * will stop discovery when finished. | 2857 | * will stop discovery when finished. If we will resolve |
| 2858 | * remote device name, do not change discovery state. | ||
| 2857 | */ | 2859 | */ |
| 2858 | if (!test_bit(HCI_INQUIRY, &hdev->flags)) | 2860 | if (!test_bit(HCI_INQUIRY, &hdev->flags) && |
| 2861 | hdev->discovery.state != DISCOVERY_RESOLVING) | ||
| 2859 | hci_discovery_set_state(hdev, | 2862 | hci_discovery_set_state(hdev, |
| 2860 | DISCOVERY_STOPPED); | 2863 | DISCOVERY_STOPPED); |
| 2861 | } else { | 2864 | } else { |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index e0670d7054f9..659fb96672e4 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -796,9 +796,11 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p, | |||
| 796 | int err = 0; | 796 | int err = 0; |
| 797 | 797 | ||
| 798 | if (ndm->ndm_flags & NTF_USE) { | 798 | if (ndm->ndm_flags & NTF_USE) { |
| 799 | local_bh_disable(); | ||
| 799 | rcu_read_lock(); | 800 | rcu_read_lock(); |
| 800 | br_fdb_update(p->br, p, addr, vid, true); | 801 | br_fdb_update(p->br, p, addr, vid, true); |
| 801 | rcu_read_unlock(); | 802 | rcu_read_unlock(); |
| 803 | local_bh_enable(); | ||
| 802 | } else { | 804 | } else { |
| 803 | spin_lock_bh(&p->br->hash_lock); | 805 | spin_lock_bh(&p->br->hash_lock); |
| 804 | err = fdb_add_entry(p, addr, ndm->ndm_state, | 806 | err = fdb_add_entry(p, addr, ndm->ndm_state, |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 409608960899..e29ad70b3000 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
| @@ -170,7 +170,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb, | |||
| 170 | struct br_port_msg *bpm; | 170 | struct br_port_msg *bpm; |
| 171 | struct nlattr *nest, *nest2; | 171 | struct nlattr *nest, *nest2; |
| 172 | 172 | ||
| 173 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI); | 173 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0); |
| 174 | if (!nlh) | 174 | if (!nlh) |
| 175 | return -EMSGSIZE; | 175 | return -EMSGSIZE; |
| 176 | 176 | ||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 4b6722f8f179..ff667e18b2d6 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1072,7 +1072,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
| 1072 | 1072 | ||
| 1073 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, | 1073 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, |
| 1074 | vid); | 1074 | vid); |
| 1075 | if (!err) | 1075 | if (err) |
| 1076 | break; | 1076 | break; |
| 1077 | } | 1077 | } |
| 1078 | 1078 | ||
| @@ -1167,6 +1167,9 @@ static void br_multicast_add_router(struct net_bridge *br, | |||
| 1167 | struct net_bridge_port *p; | 1167 | struct net_bridge_port *p; |
| 1168 | struct hlist_node *slot = NULL; | 1168 | struct hlist_node *slot = NULL; |
| 1169 | 1169 | ||
| 1170 | if (!hlist_unhashed(&port->rlist)) | ||
| 1171 | return; | ||
| 1172 | |||
| 1170 | hlist_for_each_entry(p, &br->router_list, rlist) { | 1173 | hlist_for_each_entry(p, &br->router_list, rlist) { |
| 1171 | if ((unsigned long) port >= (unsigned long) p) | 1174 | if ((unsigned long) port >= (unsigned long) p) |
| 1172 | break; | 1175 | break; |
| @@ -1194,12 +1197,8 @@ static void br_multicast_mark_router(struct net_bridge *br, | |||
| 1194 | if (port->multicast_router != 1) | 1197 | if (port->multicast_router != 1) |
| 1195 | return; | 1198 | return; |
| 1196 | 1199 | ||
| 1197 | if (!hlist_unhashed(&port->rlist)) | ||
| 1198 | goto timer; | ||
| 1199 | |||
| 1200 | br_multicast_add_router(br, port); | 1200 | br_multicast_add_router(br, port); |
| 1201 | 1201 | ||
| 1202 | timer: | ||
| 1203 | mod_timer(&port->multicast_router_timer, | 1202 | mod_timer(&port->multicast_router_timer, |
| 1204 | now + br->multicast_querier_interval); | 1203 | now + br->multicast_querier_interval); |
| 1205 | } | 1204 | } |
| @@ -1822,7 +1821,7 @@ static void br_multicast_query_expired(struct net_bridge *br, | |||
| 1822 | if (query->startup_sent < br->multicast_startup_query_count) | 1821 | if (query->startup_sent < br->multicast_startup_query_count) |
| 1823 | query->startup_sent++; | 1822 | query->startup_sent++; |
| 1824 | 1823 | ||
| 1825 | RCU_INIT_POINTER(querier, NULL); | 1824 | RCU_INIT_POINTER(querier->port, NULL); |
| 1826 | br_multicast_send_query(br, NULL, query); | 1825 | br_multicast_send_query(br, NULL, query); |
| 1827 | spin_unlock(&br->multicast_lock); | 1826 | spin_unlock(&br->multicast_lock); |
| 1828 | } | 1827 | } |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index ab55e2472beb..60ddfbeb47f5 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -37,10 +37,6 @@ | |||
| 37 | #include <net/route.h> | 37 | #include <net/route.h> |
| 38 | #include <net/netfilter/br_netfilter.h> | 38 | #include <net/netfilter/br_netfilter.h> |
| 39 | 39 | ||
| 40 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | ||
| 41 | #include <net/netfilter/nf_conntrack.h> | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 45 | #include "br_private.h" | 41 | #include "br_private.h" |
| 46 | #ifdef CONFIG_SYSCTL | 42 | #ifdef CONFIG_SYSCTL |
| @@ -350,24 +346,15 @@ free_skb: | |||
| 350 | return 0; | 346 | return 0; |
| 351 | } | 347 | } |
| 352 | 348 | ||
| 353 | static bool dnat_took_place(const struct sk_buff *skb) | 349 | static bool daddr_was_changed(const struct sk_buff *skb, |
| 350 | const struct nf_bridge_info *nf_bridge) | ||
| 354 | { | 351 | { |
| 355 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 352 | return ip_hdr(skb)->daddr != nf_bridge->ipv4_daddr; |
| 356 | enum ip_conntrack_info ctinfo; | ||
| 357 | struct nf_conn *ct; | ||
| 358 | |||
| 359 | ct = nf_ct_get(skb, &ctinfo); | ||
| 360 | if (!ct || nf_ct_is_untracked(ct)) | ||
| 361 | return false; | ||
| 362 | |||
| 363 | return test_bit(IPS_DST_NAT_BIT, &ct->status); | ||
| 364 | #else | ||
| 365 | return false; | ||
| 366 | #endif | ||
| 367 | } | 353 | } |
| 368 | 354 | ||
| 369 | /* This requires some explaining. If DNAT has taken place, | 355 | /* This requires some explaining. If DNAT has taken place, |
| 370 | * we will need to fix up the destination Ethernet address. | 356 | * we will need to fix up the destination Ethernet address. |
| 357 | * This is also true when SNAT takes place (for the reply direction). | ||
| 371 | * | 358 | * |
| 372 | * There are two cases to consider: | 359 | * There are two cases to consider: |
| 373 | * 1. The packet was DNAT'ed to a device in the same bridge | 360 | * 1. The packet was DNAT'ed to a device in the same bridge |
| @@ -421,7 +408,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb) | |||
| 421 | nf_bridge->pkt_otherhost = false; | 408 | nf_bridge->pkt_otherhost = false; |
| 422 | } | 409 | } |
| 423 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | 410 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; |
| 424 | if (dnat_took_place(skb)) { | 411 | if (daddr_was_changed(skb, nf_bridge)) { |
| 425 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { | 412 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { |
| 426 | struct in_device *in_dev = __in_dev_get_rcu(dev); | 413 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
| 427 | 414 | ||
| @@ -632,6 +619,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, | |||
| 632 | struct sk_buff *skb, | 619 | struct sk_buff *skb, |
| 633 | const struct nf_hook_state *state) | 620 | const struct nf_hook_state *state) |
| 634 | { | 621 | { |
| 622 | struct nf_bridge_info *nf_bridge; | ||
| 635 | struct net_bridge_port *p; | 623 | struct net_bridge_port *p; |
| 636 | struct net_bridge *br; | 624 | struct net_bridge *br; |
| 637 | __u32 len = nf_bridge_encap_header_len(skb); | 625 | __u32 len = nf_bridge_encap_header_len(skb); |
| @@ -669,6 +657,9 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, | |||
| 669 | if (!setup_pre_routing(skb)) | 657 | if (!setup_pre_routing(skb)) |
| 670 | return NF_DROP; | 658 | return NF_DROP; |
| 671 | 659 | ||
| 660 | nf_bridge = nf_bridge_info_get(skb); | ||
| 661 | nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; | ||
| 662 | |||
| 672 | skb->protocol = htons(ETH_P_IP); | 663 | skb->protocol = htons(ETH_P_IP); |
| 673 | 664 | ||
| 674 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, | 665 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 0e4ddb81610d..4b5c236998ff 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
| @@ -394,7 +394,7 @@ errout: | |||
| 394 | * Dump information about all ports, in response to GETLINK | 394 | * Dump information about all ports, in response to GETLINK |
| 395 | */ | 395 | */ |
| 396 | int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, | 396 | int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, |
| 397 | struct net_device *dev, u32 filter_mask) | 397 | struct net_device *dev, u32 filter_mask, int nlflags) |
| 398 | { | 398 | { |
| 399 | struct net_bridge_port *port = br_port_get_rtnl(dev); | 399 | struct net_bridge_port *port = br_port_get_rtnl(dev); |
| 400 | 400 | ||
| @@ -402,7 +402,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, | |||
| 402 | !(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) | 402 | !(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) |
| 403 | return 0; | 403 | return 0; |
| 404 | 404 | ||
| 405 | return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI, | 405 | return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, nlflags, |
| 406 | filter_mask, dev); | 406 | filter_mask, dev); |
| 407 | } | 407 | } |
| 408 | 408 | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 6ca0251cb478..3362c29400f1 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -828,7 +828,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port); | |||
| 828 | int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); | 828 | int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); |
| 829 | int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); | 829 | int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); |
| 830 | int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, | 830 | int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, |
| 831 | u32 filter_mask); | 831 | u32 filter_mask, int nlflags); |
| 832 | 832 | ||
| 833 | #ifdef CONFIG_SYSFS | 833 | #ifdef CONFIG_SYSFS |
| 834 | /* br_sysfs_if.c */ | 834 | /* br_sysfs_if.c */ |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 4fcaa67750fd..7caf7fae2d5b 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
| @@ -97,7 +97,9 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
| 97 | netif_carrier_on(br->dev); | 97 | netif_carrier_on(br->dev); |
| 98 | } | 98 | } |
| 99 | br_log_state(p); | 99 | br_log_state(p); |
| 100 | rcu_read_lock(); | ||
| 100 | br_ifinfo_notify(RTM_NEWLINK, p); | 101 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 102 | rcu_read_unlock(); | ||
| 101 | spin_unlock(&br->lock); | 103 | spin_unlock(&br->lock); |
| 102 | } | 104 | } |
| 103 | 105 | ||
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 4ec0c803aef1..112ad784838a 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
| @@ -330,6 +330,10 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) | |||
| 330 | release_sock(sk); | 330 | release_sock(sk); |
| 331 | timeo = schedule_timeout(timeo); | 331 | timeo = schedule_timeout(timeo); |
| 332 | lock_sock(sk); | 332 | lock_sock(sk); |
| 333 | |||
| 334 | if (sock_flag(sk, SOCK_DEAD)) | ||
| 335 | break; | ||
| 336 | |||
| 333 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 337 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 334 | } | 338 | } |
| 335 | 339 | ||
| @@ -373,6 +377,10 @@ static int caif_stream_recvmsg(struct socket *sock, struct msghdr *msg, | |||
| 373 | struct sk_buff *skb; | 377 | struct sk_buff *skb; |
| 374 | 378 | ||
| 375 | lock_sock(sk); | 379 | lock_sock(sk); |
| 380 | if (sock_flag(sk, SOCK_DEAD)) { | ||
| 381 | err = -ECONNRESET; | ||
| 382 | goto unlock; | ||
| 383 | } | ||
| 376 | skb = skb_dequeue(&sk->sk_receive_queue); | 384 | skb = skb_dequeue(&sk->sk_receive_queue); |
| 377 | caif_check_flow_release(sk); | 385 | caif_check_flow_release(sk); |
| 378 | 386 | ||
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 41a4abc7e98e..c4ec9239249a 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -1306,8 +1306,6 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc, | |||
| 1306 | if (list_empty(&req->r_osd_item)) | 1306 | if (list_empty(&req->r_osd_item)) |
| 1307 | req->r_osd = NULL; | 1307 | req->r_osd = NULL; |
| 1308 | } | 1308 | } |
| 1309 | |||
| 1310 | list_del_init(&req->r_req_lru_item); /* can be on notarget */ | ||
| 1311 | ceph_osdc_put_request(req); | 1309 | ceph_osdc_put_request(req); |
| 1312 | } | 1310 | } |
| 1313 | 1311 | ||
| @@ -2017,20 +2015,29 @@ static void kick_requests(struct ceph_osd_client *osdc, bool force_resend, | |||
| 2017 | err = __map_request(osdc, req, | 2015 | err = __map_request(osdc, req, |
| 2018 | force_resend || force_resend_writes); | 2016 | force_resend || force_resend_writes); |
| 2019 | dout("__map_request returned %d\n", err); | 2017 | dout("__map_request returned %d\n", err); |
| 2020 | if (err == 0) | ||
| 2021 | continue; /* no change and no osd was specified */ | ||
| 2022 | if (err < 0) | 2018 | if (err < 0) |
| 2023 | continue; /* hrm! */ | 2019 | continue; /* hrm! */ |
| 2024 | if (req->r_osd == NULL) { | 2020 | if (req->r_osd == NULL || err > 0) { |
| 2025 | dout("tid %llu maps to no valid osd\n", req->r_tid); | 2021 | if (req->r_osd == NULL) { |
| 2026 | needmap++; /* request a newer map */ | 2022 | dout("lingering %p tid %llu maps to no osd\n", |
| 2027 | continue; | 2023 | req, req->r_tid); |
| 2028 | } | 2024 | /* |
| 2025 | * A homeless lingering request makes | ||
| 2026 | * no sense, as it's job is to keep | ||
| 2027 | * a particular OSD connection open. | ||
| 2028 | * Request a newer map and kick the | ||
| 2029 | * request, knowing that it won't be | ||
| 2030 | * resent until we actually get a map | ||
| 2031 | * that can tell us where to send it. | ||
| 2032 | */ | ||
| 2033 | needmap++; | ||
| 2034 | } | ||
| 2029 | 2035 | ||
| 2030 | dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, | 2036 | dout("kicking lingering %p tid %llu osd%d\n", req, |
| 2031 | req->r_osd ? req->r_osd->o_osd : -1); | 2037 | req->r_tid, req->r_osd ? req->r_osd->o_osd : -1); |
| 2032 | __register_request(osdc, req); | 2038 | __register_request(osdc, req); |
| 2033 | __unregister_linger_request(osdc, req); | 2039 | __unregister_linger_request(osdc, req); |
| 2040 | } | ||
| 2034 | } | 2041 | } |
| 2035 | reset_changed_osds(osdc); | 2042 | reset_changed_osds(osdc); |
| 2036 | mutex_unlock(&osdc->request_mutex); | 2043 | mutex_unlock(&osdc->request_mutex); |
diff --git a/net/core/dev.c b/net/core/dev.c index 1796cef55ab5..aa82f9ab6a36 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1718,15 +1718,8 @@ EXPORT_SYMBOL_GPL(is_skb_forwardable); | |||
| 1718 | 1718 | ||
| 1719 | int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb) | 1719 | int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb) |
| 1720 | { | 1720 | { |
| 1721 | if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { | 1721 | if (skb_orphan_frags(skb, GFP_ATOMIC) || |
| 1722 | if (skb_copy_ubufs(skb, GFP_ATOMIC)) { | 1722 | unlikely(!is_skb_forwardable(dev, skb))) { |
| 1723 | atomic_long_inc(&dev->rx_dropped); | ||
| 1724 | kfree_skb(skb); | ||
| 1725 | return NET_RX_DROP; | ||
| 1726 | } | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | if (unlikely(!is_skb_forwardable(dev, skb))) { | ||
| 1730 | atomic_long_inc(&dev->rx_dropped); | 1723 | atomic_long_inc(&dev->rx_dropped); |
| 1731 | kfree_skb(skb); | 1724 | kfree_skb(skb); |
| 1732 | return NET_RX_DROP; | 1725 | return NET_RX_DROP; |
| @@ -3079,7 +3072,7 @@ static struct rps_dev_flow * | |||
| 3079 | set_rps_cpu(struct net_device *dev, struct sk_buff *skb, | 3072 | set_rps_cpu(struct net_device *dev, struct sk_buff *skb, |
| 3080 | struct rps_dev_flow *rflow, u16 next_cpu) | 3073 | struct rps_dev_flow *rflow, u16 next_cpu) |
| 3081 | { | 3074 | { |
| 3082 | if (next_cpu != RPS_NO_CPU) { | 3075 | if (next_cpu < nr_cpu_ids) { |
| 3083 | #ifdef CONFIG_RFS_ACCEL | 3076 | #ifdef CONFIG_RFS_ACCEL |
| 3084 | struct netdev_rx_queue *rxqueue; | 3077 | struct netdev_rx_queue *rxqueue; |
| 3085 | struct rps_dev_flow_table *flow_table; | 3078 | struct rps_dev_flow_table *flow_table; |
| @@ -3184,7 +3177,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 3184 | * If the desired CPU (where last recvmsg was done) is | 3177 | * If the desired CPU (where last recvmsg was done) is |
| 3185 | * different from current CPU (one in the rx-queue flow | 3178 | * different from current CPU (one in the rx-queue flow |
| 3186 | * table entry), switch if one of the following holds: | 3179 | * table entry), switch if one of the following holds: |
| 3187 | * - Current CPU is unset (equal to RPS_NO_CPU). | 3180 | * - Current CPU is unset (>= nr_cpu_ids). |
| 3188 | * - Current CPU is offline. | 3181 | * - Current CPU is offline. |
| 3189 | * - The current CPU's queue tail has advanced beyond the | 3182 | * - The current CPU's queue tail has advanced beyond the |
| 3190 | * last packet that was enqueued using this table entry. | 3183 | * last packet that was enqueued using this table entry. |
| @@ -3192,14 +3185,14 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 3192 | * have been dequeued, thus preserving in order delivery. | 3185 | * have been dequeued, thus preserving in order delivery. |
| 3193 | */ | 3186 | */ |
| 3194 | if (unlikely(tcpu != next_cpu) && | 3187 | if (unlikely(tcpu != next_cpu) && |
| 3195 | (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || | 3188 | (tcpu >= nr_cpu_ids || !cpu_online(tcpu) || |
| 3196 | ((int)(per_cpu(softnet_data, tcpu).input_queue_head - | 3189 | ((int)(per_cpu(softnet_data, tcpu).input_queue_head - |
| 3197 | rflow->last_qtail)) >= 0)) { | 3190 | rflow->last_qtail)) >= 0)) { |
| 3198 | tcpu = next_cpu; | 3191 | tcpu = next_cpu; |
| 3199 | rflow = set_rps_cpu(dev, skb, rflow, next_cpu); | 3192 | rflow = set_rps_cpu(dev, skb, rflow, next_cpu); |
| 3200 | } | 3193 | } |
| 3201 | 3194 | ||
| 3202 | if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { | 3195 | if (tcpu < nr_cpu_ids && cpu_online(tcpu)) { |
| 3203 | *rflowp = rflow; | 3196 | *rflowp = rflow; |
| 3204 | cpu = tcpu; | 3197 | cpu = tcpu; |
| 3205 | goto done; | 3198 | goto done; |
| @@ -3240,14 +3233,14 @@ bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, | |||
| 3240 | struct rps_dev_flow_table *flow_table; | 3233 | struct rps_dev_flow_table *flow_table; |
| 3241 | struct rps_dev_flow *rflow; | 3234 | struct rps_dev_flow *rflow; |
| 3242 | bool expire = true; | 3235 | bool expire = true; |
| 3243 | int cpu; | 3236 | unsigned int cpu; |
| 3244 | 3237 | ||
| 3245 | rcu_read_lock(); | 3238 | rcu_read_lock(); |
| 3246 | flow_table = rcu_dereference(rxqueue->rps_flow_table); | 3239 | flow_table = rcu_dereference(rxqueue->rps_flow_table); |
| 3247 | if (flow_table && flow_id <= flow_table->mask) { | 3240 | if (flow_table && flow_id <= flow_table->mask) { |
| 3248 | rflow = &flow_table->flows[flow_id]; | 3241 | rflow = &flow_table->flows[flow_id]; |
| 3249 | cpu = ACCESS_ONCE(rflow->cpu); | 3242 | cpu = ACCESS_ONCE(rflow->cpu); |
| 3250 | if (rflow->filter == filter_id && cpu != RPS_NO_CPU && | 3243 | if (rflow->filter == filter_id && cpu < nr_cpu_ids && |
| 3251 | ((int)(per_cpu(softnet_data, cpu).input_queue_head - | 3244 | ((int)(per_cpu(softnet_data, cpu).input_queue_head - |
| 3252 | rflow->last_qtail) < | 3245 | rflow->last_qtail) < |
| 3253 | (int)(10 * flow_table->mask))) | 3246 | (int)(10 * flow_table->mask))) |
| @@ -5209,7 +5202,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
| 5209 | if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) | 5202 | if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) |
| 5210 | return -EBUSY; | 5203 | return -EBUSY; |
| 5211 | 5204 | ||
| 5212 | if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper)) | 5205 | if (__netdev_find_adj(dev, upper_dev, &dev->adj_list.upper)) |
| 5213 | return -EEXIST; | 5206 | return -EEXIST; |
| 5214 | 5207 | ||
| 5215 | if (master && netdev_master_upper_dev_get(dev)) | 5208 | if (master && netdev_master_upper_dev_get(dev)) |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 78fc04ad36fc..572af0011997 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
| @@ -601,7 +601,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, | 603 | err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, |
| 604 | RTM_GETNSID, net, peer, -1); | 604 | RTM_NEWNSID, net, peer, -1); |
| 605 | if (err < 0) | 605 | if (err < 0) |
| 606 | goto err_out; | 606 | goto err_out; |
| 607 | 607 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 358d52a38533..8de36824018d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -2416,6 +2416,9 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change, | |||
| 2416 | { | 2416 | { |
| 2417 | struct sk_buff *skb; | 2417 | struct sk_buff *skb; |
| 2418 | 2418 | ||
| 2419 | if (dev->reg_state != NETREG_REGISTERED) | ||
| 2420 | return; | ||
| 2421 | |||
| 2419 | skb = rtmsg_ifinfo_build_skb(type, dev, change, flags); | 2422 | skb = rtmsg_ifinfo_build_skb(type, dev, change, flags); |
| 2420 | if (skb) | 2423 | if (skb) |
| 2421 | rtmsg_ifinfo_send(skb, dev, flags); | 2424 | rtmsg_ifinfo_send(skb, dev, flags); |
| @@ -2854,7 +2857,7 @@ static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask, | |||
| 2854 | 2857 | ||
| 2855 | int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, | 2858 | int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, |
| 2856 | struct net_device *dev, u16 mode, | 2859 | struct net_device *dev, u16 mode, |
| 2857 | u32 flags, u32 mask) | 2860 | u32 flags, u32 mask, int nlflags) |
| 2858 | { | 2861 | { |
| 2859 | struct nlmsghdr *nlh; | 2862 | struct nlmsghdr *nlh; |
| 2860 | struct ifinfomsg *ifm; | 2863 | struct ifinfomsg *ifm; |
| @@ -2863,7 +2866,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, | |||
| 2863 | u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; | 2866 | u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; |
| 2864 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); | 2867 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
| 2865 | 2868 | ||
| 2866 | nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI); | 2869 | nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), nlflags); |
| 2867 | if (nlh == NULL) | 2870 | if (nlh == NULL) |
| 2868 | return -EMSGSIZE; | 2871 | return -EMSGSIZE; |
| 2869 | 2872 | ||
| @@ -2969,7 +2972,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2969 | if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { | 2972 | if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { |
| 2970 | if (idx >= cb->args[0] && | 2973 | if (idx >= cb->args[0] && |
| 2971 | br_dev->netdev_ops->ndo_bridge_getlink( | 2974 | br_dev->netdev_ops->ndo_bridge_getlink( |
| 2972 | skb, portid, seq, dev, filter_mask) < 0) | 2975 | skb, portid, seq, dev, filter_mask, |
| 2976 | NLM_F_MULTI) < 0) | ||
| 2973 | break; | 2977 | break; |
| 2974 | idx++; | 2978 | idx++; |
| 2975 | } | 2979 | } |
| @@ -2977,7 +2981,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2977 | if (ops->ndo_bridge_getlink) { | 2981 | if (ops->ndo_bridge_getlink) { |
| 2978 | if (idx >= cb->args[0] && | 2982 | if (idx >= cb->args[0] && |
| 2979 | ops->ndo_bridge_getlink(skb, portid, seq, dev, | 2983 | ops->ndo_bridge_getlink(skb, portid, seq, dev, |
| 2980 | filter_mask) < 0) | 2984 | filter_mask, |
| 2985 | NLM_F_MULTI) < 0) | ||
| 2981 | break; | 2986 | break; |
| 2982 | idx++; | 2987 | idx++; |
| 2983 | } | 2988 | } |
| @@ -3018,7 +3023,7 @@ static int rtnl_bridge_notify(struct net_device *dev) | |||
| 3018 | goto errout; | 3023 | goto errout; |
| 3019 | } | 3024 | } |
| 3020 | 3025 | ||
| 3021 | err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0); | 3026 | err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0); |
| 3022 | if (err < 0) | 3027 | if (err < 0) |
| 3023 | goto errout; | 3028 | goto errout; |
| 3024 | 3029 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d1967dab9cc6..41ec02242ea7 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -280,13 +280,14 @@ nodata: | |||
| 280 | EXPORT_SYMBOL(__alloc_skb); | 280 | EXPORT_SYMBOL(__alloc_skb); |
| 281 | 281 | ||
| 282 | /** | 282 | /** |
| 283 | * build_skb - build a network buffer | 283 | * __build_skb - build a network buffer |
| 284 | * @data: data buffer provided by caller | 284 | * @data: data buffer provided by caller |
| 285 | * @frag_size: size of fragment, or 0 if head was kmalloced | 285 | * @frag_size: size of data, or 0 if head was kmalloced |
| 286 | * | 286 | * |
| 287 | * Allocate a new &sk_buff. Caller provides space holding head and | 287 | * Allocate a new &sk_buff. Caller provides space holding head and |
| 288 | * skb_shared_info. @data must have been allocated by kmalloc() only if | 288 | * skb_shared_info. @data must have been allocated by kmalloc() only if |
| 289 | * @frag_size is 0, otherwise data should come from the page allocator. | 289 | * @frag_size is 0, otherwise data should come from the page allocator |
| 290 | * or vmalloc() | ||
| 290 | * The return is the new skb buffer. | 291 | * The return is the new skb buffer. |
| 291 | * On a failure the return is %NULL, and @data is not freed. | 292 | * On a failure the return is %NULL, and @data is not freed. |
| 292 | * Notes : | 293 | * Notes : |
| @@ -297,7 +298,7 @@ EXPORT_SYMBOL(__alloc_skb); | |||
| 297 | * before giving packet to stack. | 298 | * before giving packet to stack. |
| 298 | * RX rings only contains data buffers, not full skbs. | 299 | * RX rings only contains data buffers, not full skbs. |
| 299 | */ | 300 | */ |
| 300 | struct sk_buff *build_skb(void *data, unsigned int frag_size) | 301 | struct sk_buff *__build_skb(void *data, unsigned int frag_size) |
| 301 | { | 302 | { |
| 302 | struct skb_shared_info *shinfo; | 303 | struct skb_shared_info *shinfo; |
| 303 | struct sk_buff *skb; | 304 | struct sk_buff *skb; |
| @@ -311,7 +312,6 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) | |||
| 311 | 312 | ||
| 312 | memset(skb, 0, offsetof(struct sk_buff, tail)); | 313 | memset(skb, 0, offsetof(struct sk_buff, tail)); |
| 313 | skb->truesize = SKB_TRUESIZE(size); | 314 | skb->truesize = SKB_TRUESIZE(size); |
| 314 | skb->head_frag = frag_size != 0; | ||
| 315 | atomic_set(&skb->users, 1); | 315 | atomic_set(&skb->users, 1); |
| 316 | skb->head = data; | 316 | skb->head = data; |
| 317 | skb->data = data; | 317 | skb->data = data; |
| @@ -328,6 +328,23 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) | |||
| 328 | 328 | ||
| 329 | return skb; | 329 | return skb; |
| 330 | } | 330 | } |
| 331 | |||
| 332 | /* build_skb() is wrapper over __build_skb(), that specifically | ||
| 333 | * takes care of skb->head and skb->pfmemalloc | ||
| 334 | * This means that if @frag_size is not zero, then @data must be backed | ||
| 335 | * by a page fragment, not kmalloc() or vmalloc() | ||
| 336 | */ | ||
| 337 | struct sk_buff *build_skb(void *data, unsigned int frag_size) | ||
| 338 | { | ||
| 339 | struct sk_buff *skb = __build_skb(data, frag_size); | ||
| 340 | |||
| 341 | if (skb && frag_size) { | ||
| 342 | skb->head_frag = 1; | ||
| 343 | if (virt_to_head_page(data)->pfmemalloc) | ||
| 344 | skb->pfmemalloc = 1; | ||
| 345 | } | ||
| 346 | return skb; | ||
| 347 | } | ||
| 331 | EXPORT_SYMBOL(build_skb); | 348 | EXPORT_SYMBOL(build_skb); |
| 332 | 349 | ||
| 333 | struct netdev_alloc_cache { | 350 | struct netdev_alloc_cache { |
| @@ -348,7 +365,8 @@ static struct page *__page_frag_refill(struct netdev_alloc_cache *nc, | |||
| 348 | gfp_t gfp = gfp_mask; | 365 | gfp_t gfp = gfp_mask; |
| 349 | 366 | ||
| 350 | if (order) { | 367 | if (order) { |
| 351 | gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; | 368 | gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY | |
| 369 | __GFP_NOMEMALLOC; | ||
| 352 | page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order); | 370 | page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order); |
| 353 | nc->frag.size = PAGE_SIZE << (page ? order : 0); | 371 | nc->frag.size = PAGE_SIZE << (page ? order : 0); |
| 354 | } | 372 | } |
| @@ -4380,7 +4398,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len, | |||
| 4380 | 4398 | ||
| 4381 | while (order) { | 4399 | while (order) { |
| 4382 | if (npages >= 1 << order) { | 4400 | if (npages >= 1 << order) { |
| 4383 | page = alloc_pages(gfp_mask | | 4401 | page = alloc_pages((gfp_mask & ~__GFP_WAIT) | |
| 4384 | __GFP_COMP | | 4402 | __GFP_COMP | |
| 4385 | __GFP_NOWARN | | 4403 | __GFP_NOWARN | |
| 4386 | __GFP_NORETRY, | 4404 | __GFP_NORETRY, |
diff --git a/net/core/sock.c b/net/core/sock.c index e891bcf325ca..dc30dc5bb1b8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -354,15 +354,12 @@ void sk_clear_memalloc(struct sock *sk) | |||
| 354 | 354 | ||
| 355 | /* | 355 | /* |
| 356 | * SOCK_MEMALLOC is allowed to ignore rmem limits to ensure forward | 356 | * SOCK_MEMALLOC is allowed to ignore rmem limits to ensure forward |
| 357 | * progress of swapping. However, if SOCK_MEMALLOC is cleared while | 357 | * progress of swapping. SOCK_MEMALLOC may be cleared while |
| 358 | * it has rmem allocations there is a risk that the user of the | 358 | * it has rmem allocations due to the last swapfile being deactivated |
| 359 | * socket cannot make forward progress due to exceeding the rmem | 359 | * but there is a risk that the socket is unusable due to exceeding |
| 360 | * limits. By rights, sk_clear_memalloc() should only be called | 360 | * the rmem limits. Reclaim the reserves and obey rmem limits again. |
| 361 | * on sockets being torn down but warn and reset the accounting if | ||
| 362 | * that assumption breaks. | ||
| 363 | */ | 361 | */ |
| 364 | if (WARN_ON(sk->sk_forward_alloc)) | 362 | sk_mem_reclaim(sk); |
| 365 | sk_mem_reclaim(sk); | ||
| 366 | } | 363 | } |
| 367 | EXPORT_SYMBOL_GPL(sk_clear_memalloc); | 364 | EXPORT_SYMBOL_GPL(sk_clear_memalloc); |
| 368 | 365 | ||
| @@ -1474,8 +1471,8 @@ void sk_release_kernel(struct sock *sk) | |||
| 1474 | return; | 1471 | return; |
| 1475 | 1472 | ||
| 1476 | sock_hold(sk); | 1473 | sock_hold(sk); |
| 1477 | sock_net_set(sk, get_net(&init_net)); | ||
| 1478 | sock_release(sk->sk_socket); | 1474 | sock_release(sk->sk_socket); |
| 1475 | sock_net_set(sk, get_net(&init_net)); | ||
| 1479 | sock_put(sk); | 1476 | sock_put(sk); |
| 1480 | } | 1477 | } |
| 1481 | EXPORT_SYMBOL(sk_release_kernel); | 1478 | EXPORT_SYMBOL(sk_release_kernel); |
| @@ -1883,7 +1880,7 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp) | |||
| 1883 | 1880 | ||
| 1884 | pfrag->offset = 0; | 1881 | pfrag->offset = 0; |
| 1885 | if (SKB_FRAG_PAGE_ORDER) { | 1882 | if (SKB_FRAG_PAGE_ORDER) { |
| 1886 | pfrag->page = alloc_pages(gfp | __GFP_COMP | | 1883 | pfrag->page = alloc_pages((gfp & ~__GFP_WAIT) | __GFP_COMP | |
| 1887 | __GFP_NOWARN | __GFP_NORETRY, | 1884 | __GFP_NOWARN | __GFP_NORETRY, |
| 1888 | SKB_FRAG_PAGE_ORDER); | 1885 | SKB_FRAG_PAGE_ORDER); |
| 1889 | if (likely(pfrag->page)) { | 1886 | if (likely(pfrag->page)) { |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 2b4f21d34df6..ccf4c5629b3c 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
| @@ -453,7 +453,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
| 453 | iph->saddr, iph->daddr); | 453 | iph->saddr, iph->daddr); |
| 454 | if (req) { | 454 | if (req) { |
| 455 | nsk = dccp_check_req(sk, skb, req); | 455 | nsk = dccp_check_req(sk, skb, req); |
| 456 | reqsk_put(req); | 456 | if (!nsk) |
| 457 | reqsk_put(req); | ||
| 457 | return nsk; | 458 | return nsk; |
| 458 | } | 459 | } |
| 459 | nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo, | 460 | nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo, |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 9d0551092c6c..5165571f397a 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
| @@ -301,7 +301,8 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
| 301 | &iph->daddr, inet6_iif(skb)); | 301 | &iph->daddr, inet6_iif(skb)); |
| 302 | if (req) { | 302 | if (req) { |
| 303 | nsk = dccp_check_req(sk, skb, req); | 303 | nsk = dccp_check_req(sk, skb, req); |
| 304 | reqsk_put(req); | 304 | if (!nsk) |
| 305 | reqsk_put(req); | ||
| 305 | return nsk; | 306 | return nsk; |
| 306 | } | 307 | } |
| 307 | nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo, | 308 | nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo, |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 5f566663e47f..30addee2dd03 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
| @@ -186,8 +186,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb, | |||
| 186 | if (child == NULL) | 186 | if (child == NULL) |
| 187 | goto listen_overflow; | 187 | goto listen_overflow; |
| 188 | 188 | ||
| 189 | inet_csk_reqsk_queue_unlink(sk, req); | 189 | inet_csk_reqsk_queue_drop(sk, req); |
| 190 | inet_csk_reqsk_queue_removed(sk, req); | ||
| 191 | inet_csk_reqsk_queue_add(sk, req, child); | 190 | inet_csk_reqsk_queue_add(sk, req, child); |
| 192 | out: | 191 | out: |
| 193 | return child; | 192 | return child; |
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 079a224471e7..392e29a0227d 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
| @@ -359,7 +359,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, | |||
| 359 | */ | 359 | */ |
| 360 | ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL); | 360 | ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL); |
| 361 | if (ds == NULL) | 361 | if (ds == NULL) |
| 362 | return NULL; | 362 | return ERR_PTR(-ENOMEM); |
| 363 | 363 | ||
| 364 | ds->dst = dst; | 364 | ds->dst = dst; |
| 365 | ds->index = index; | 365 | ds->index = index; |
| @@ -370,7 +370,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, | |||
| 370 | 370 | ||
| 371 | ret = dsa_switch_setup_one(ds, parent); | 371 | ret = dsa_switch_setup_one(ds, parent); |
| 372 | if (ret) | 372 | if (ret) |
| 373 | return NULL; | 373 | return ERR_PTR(ret); |
| 374 | 374 | ||
| 375 | return ds; | 375 | return ds; |
| 376 | } | 376 | } |
| @@ -633,7 +633,7 @@ static int dsa_of_probe(struct device *dev) | |||
| 633 | if (cd->sw_addr > PHY_MAX_ADDR) | 633 | if (cd->sw_addr > PHY_MAX_ADDR) |
| 634 | continue; | 634 | continue; |
| 635 | 635 | ||
| 636 | if (!of_property_read_u32(np, "eeprom-length", &eeprom_len)) | 636 | if (!of_property_read_u32(child, "eeprom-length", &eeprom_len)) |
| 637 | cd->eeprom_len = eeprom_len; | 637 | cd->eeprom_len = eeprom_len; |
| 638 | 638 | ||
| 639 | for_each_available_child_of_node(child, port) { | 639 | for_each_available_child_of_node(child, port) { |
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index 05dab2957cd4..4adfd4d5471b 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
| @@ -3,7 +3,9 @@ obj-$(CONFIG_IEEE802154_SOCKET) += ieee802154_socket.o | |||
| 3 | obj-y += 6lowpan/ | 3 | obj-y += 6lowpan/ |
| 4 | 4 | ||
| 5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \ | 5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \ |
| 6 | header_ops.o sysfs.o nl802154.o | 6 | header_ops.o sysfs.o nl802154.o trace.o |
| 7 | ieee802154_socket-y := socket.o | 7 | ieee802154_socket-y := socket.o |
| 8 | 8 | ||
| 9 | CFLAGS_trace.o := -I$(src) | ||
| 10 | |||
| 9 | ccflags-y += -D__CHECK_ENDIAN__ | 11 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 1b9d25f6e898..346c6665d25e 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
| @@ -175,6 +175,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
| 175 | int rc = -ENOBUFS; | 175 | int rc = -ENOBUFS; |
| 176 | struct net_device *dev; | 176 | struct net_device *dev; |
| 177 | int type = __IEEE802154_DEV_INVALID; | 177 | int type = __IEEE802154_DEV_INVALID; |
| 178 | unsigned char name_assign_type; | ||
| 178 | 179 | ||
| 179 | pr_debug("%s\n", __func__); | 180 | pr_debug("%s\n", __func__); |
| 180 | 181 | ||
| @@ -190,8 +191,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
| 190 | if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] | 191 | if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] |
| 191 | != '\0') | 192 | != '\0') |
| 192 | return -EINVAL; /* phy name should be null-terminated */ | 193 | return -EINVAL; /* phy name should be null-terminated */ |
| 194 | name_assign_type = NET_NAME_USER; | ||
| 193 | } else { | 195 | } else { |
| 194 | devname = "wpan%d"; | 196 | devname = "wpan%d"; |
| 197 | name_assign_type = NET_NAME_ENUM; | ||
| 195 | } | 198 | } |
| 196 | 199 | ||
| 197 | if (strlen(devname) >= IFNAMSIZ) | 200 | if (strlen(devname) >= IFNAMSIZ) |
| @@ -221,7 +224,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
| 221 | } | 224 | } |
| 222 | 225 | ||
| 223 | dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname, | 226 | dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname, |
| 224 | type); | 227 | name_assign_type, type); |
| 225 | if (IS_ERR(dev)) { | 228 | if (IS_ERR(dev)) { |
| 226 | rc = PTR_ERR(dev); | 229 | rc = PTR_ERR(dev); |
| 227 | goto nla_put_failure; | 230 | goto nla_put_failure; |
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index a4daf91b8d0a..f3c12f6a4a39 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c | |||
| @@ -589,7 +589,7 @@ static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 589 | 589 | ||
| 590 | return rdev_add_virtual_intf(rdev, | 590 | return rdev_add_virtual_intf(rdev, |
| 591 | nla_data(info->attrs[NL802154_ATTR_IFNAME]), | 591 | nla_data(info->attrs[NL802154_ATTR_IFNAME]), |
| 592 | type, extended_addr); | 592 | NET_NAME_USER, type, extended_addr); |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) | 595 | static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) |
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h index 7c46732fad2b..7b5a9dd94fe5 100644 --- a/net/ieee802154/rdev-ops.h +++ b/net/ieee802154/rdev-ops.h | |||
| @@ -4,13 +4,16 @@ | |||
| 4 | #include <net/cfg802154.h> | 4 | #include <net/cfg802154.h> |
| 5 | 5 | ||
| 6 | #include "core.h" | 6 | #include "core.h" |
| 7 | #include "trace.h" | ||
| 7 | 8 | ||
| 8 | static inline struct net_device * | 9 | static inline struct net_device * |
| 9 | rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | 10 | rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, |
| 10 | const char *name, int type) | 11 | const char *name, |
| 12 | unsigned char name_assign_type, | ||
| 13 | int type) | ||
| 11 | { | 14 | { |
| 12 | return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name, | 15 | return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name, |
| 13 | type); | 16 | name_assign_type, type); |
| 14 | } | 17 | } |
| 15 | 18 | ||
| 16 | static inline void | 19 | static inline void |
| @@ -22,75 +25,131 @@ rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, | |||
| 22 | 25 | ||
| 23 | static inline int | 26 | static inline int |
| 24 | rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, | 27 | rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, |
| 28 | unsigned char name_assign_type, | ||
| 25 | enum nl802154_iftype type, __le64 extended_addr) | 29 | enum nl802154_iftype type, __le64 extended_addr) |
| 26 | { | 30 | { |
| 27 | return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type, | 31 | int ret; |
| 32 | |||
| 33 | trace_802154_rdev_add_virtual_intf(&rdev->wpan_phy, name, type, | ||
| 28 | extended_addr); | 34 | extended_addr); |
| 35 | ret = rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, | ||
| 36 | name_assign_type, type, | ||
| 37 | extended_addr); | ||
| 38 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 39 | return ret; | ||
| 29 | } | 40 | } |
| 30 | 41 | ||
| 31 | static inline int | 42 | static inline int |
| 32 | rdev_del_virtual_intf(struct cfg802154_registered_device *rdev, | 43 | rdev_del_virtual_intf(struct cfg802154_registered_device *rdev, |
| 33 | struct wpan_dev *wpan_dev) | 44 | struct wpan_dev *wpan_dev) |
| 34 | { | 45 | { |
| 35 | return rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev); | 46 | int ret; |
| 47 | |||
| 48 | trace_802154_rdev_del_virtual_intf(&rdev->wpan_phy, wpan_dev); | ||
| 49 | ret = rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev); | ||
| 50 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 51 | return ret; | ||
| 36 | } | 52 | } |
| 37 | 53 | ||
| 38 | static inline int | 54 | static inline int |
| 39 | rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel) | 55 | rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel) |
| 40 | { | 56 | { |
| 41 | return rdev->ops->set_channel(&rdev->wpan_phy, page, channel); | 57 | int ret; |
| 58 | |||
| 59 | trace_802154_rdev_set_channel(&rdev->wpan_phy, page, channel); | ||
| 60 | ret = rdev->ops->set_channel(&rdev->wpan_phy, page, channel); | ||
| 61 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 62 | return ret; | ||
| 42 | } | 63 | } |
| 43 | 64 | ||
| 44 | static inline int | 65 | static inline int |
| 45 | rdev_set_cca_mode(struct cfg802154_registered_device *rdev, | 66 | rdev_set_cca_mode(struct cfg802154_registered_device *rdev, |
| 46 | const struct wpan_phy_cca *cca) | 67 | const struct wpan_phy_cca *cca) |
| 47 | { | 68 | { |
| 48 | return rdev->ops->set_cca_mode(&rdev->wpan_phy, cca); | 69 | int ret; |
| 70 | |||
| 71 | trace_802154_rdev_set_cca_mode(&rdev->wpan_phy, cca); | ||
| 72 | ret = rdev->ops->set_cca_mode(&rdev->wpan_phy, cca); | ||
| 73 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 74 | return ret; | ||
| 49 | } | 75 | } |
| 50 | 76 | ||
| 51 | static inline int | 77 | static inline int |
| 52 | rdev_set_pan_id(struct cfg802154_registered_device *rdev, | 78 | rdev_set_pan_id(struct cfg802154_registered_device *rdev, |
| 53 | struct wpan_dev *wpan_dev, __le16 pan_id) | 79 | struct wpan_dev *wpan_dev, __le16 pan_id) |
| 54 | { | 80 | { |
| 55 | return rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id); | 81 | int ret; |
| 82 | |||
| 83 | trace_802154_rdev_set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id); | ||
| 84 | ret = rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id); | ||
| 85 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 86 | return ret; | ||
| 56 | } | 87 | } |
| 57 | 88 | ||
| 58 | static inline int | 89 | static inline int |
| 59 | rdev_set_short_addr(struct cfg802154_registered_device *rdev, | 90 | rdev_set_short_addr(struct cfg802154_registered_device *rdev, |
| 60 | struct wpan_dev *wpan_dev, __le16 short_addr) | 91 | struct wpan_dev *wpan_dev, __le16 short_addr) |
| 61 | { | 92 | { |
| 62 | return rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr); | 93 | int ret; |
| 94 | |||
| 95 | trace_802154_rdev_set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr); | ||
| 96 | ret = rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr); | ||
| 97 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 98 | return ret; | ||
| 63 | } | 99 | } |
| 64 | 100 | ||
| 65 | static inline int | 101 | static inline int |
| 66 | rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev, | 102 | rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev, |
| 67 | struct wpan_dev *wpan_dev, u8 min_be, u8 max_be) | 103 | struct wpan_dev *wpan_dev, u8 min_be, u8 max_be) |
| 68 | { | 104 | { |
| 69 | return rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev, | 105 | int ret; |
| 106 | |||
| 107 | trace_802154_rdev_set_backoff_exponent(&rdev->wpan_phy, wpan_dev, | ||
| 70 | min_be, max_be); | 108 | min_be, max_be); |
| 109 | ret = rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev, | ||
| 110 | min_be, max_be); | ||
| 111 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 112 | return ret; | ||
| 71 | } | 113 | } |
| 72 | 114 | ||
| 73 | static inline int | 115 | static inline int |
| 74 | rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev, | 116 | rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev, |
| 75 | struct wpan_dev *wpan_dev, u8 max_csma_backoffs) | 117 | struct wpan_dev *wpan_dev, u8 max_csma_backoffs) |
| 76 | { | 118 | { |
| 77 | return rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev, | 119 | int ret; |
| 78 | max_csma_backoffs); | 120 | |
| 121 | trace_802154_rdev_set_csma_backoffs(&rdev->wpan_phy, wpan_dev, | ||
| 122 | max_csma_backoffs); | ||
| 123 | ret = rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev, | ||
| 124 | max_csma_backoffs); | ||
| 125 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 126 | return ret; | ||
| 79 | } | 127 | } |
| 80 | 128 | ||
| 81 | static inline int | 129 | static inline int |
| 82 | rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev, | 130 | rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev, |
| 83 | struct wpan_dev *wpan_dev, s8 max_frame_retries) | 131 | struct wpan_dev *wpan_dev, s8 max_frame_retries) |
| 84 | { | 132 | { |
| 85 | return rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev, | 133 | int ret; |
| 134 | |||
| 135 | trace_802154_rdev_set_max_frame_retries(&rdev->wpan_phy, wpan_dev, | ||
| 86 | max_frame_retries); | 136 | max_frame_retries); |
| 137 | ret = rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev, | ||
| 138 | max_frame_retries); | ||
| 139 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 140 | return ret; | ||
| 87 | } | 141 | } |
| 88 | 142 | ||
| 89 | static inline int | 143 | static inline int |
| 90 | rdev_set_lbt_mode(struct cfg802154_registered_device *rdev, | 144 | rdev_set_lbt_mode(struct cfg802154_registered_device *rdev, |
| 91 | struct wpan_dev *wpan_dev, bool mode) | 145 | struct wpan_dev *wpan_dev, bool mode) |
| 92 | { | 146 | { |
| 93 | return rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode); | 147 | int ret; |
| 148 | |||
| 149 | trace_802154_rdev_set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode); | ||
| 150 | ret = rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode); | ||
| 151 | trace_802154_rdev_return_int(&rdev->wpan_phy, ret); | ||
| 152 | return ret; | ||
| 94 | } | 153 | } |
| 95 | 154 | ||
| 96 | #endif /* __CFG802154_RDEV_OPS */ | 155 | #endif /* __CFG802154_RDEV_OPS */ |
diff --git a/net/ieee802154/trace.c b/net/ieee802154/trace.c new file mode 100644 index 000000000000..95f997fad755 --- /dev/null +++ b/net/ieee802154/trace.c | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #include <linux/module.h> | ||
| 2 | |||
| 3 | #ifndef __CHECKER__ | ||
| 4 | #define CREATE_TRACE_POINTS | ||
| 5 | #include "trace.h" | ||
| 6 | |||
| 7 | #endif | ||
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h new file mode 100644 index 000000000000..5ac25eb6ed17 --- /dev/null +++ b/net/ieee802154/trace.h | |||
| @@ -0,0 +1,247 @@ | |||
| 1 | /* Based on net/wireless/tracing.h */ | ||
| 2 | |||
| 3 | #undef TRACE_SYSTEM | ||
| 4 | #define TRACE_SYSTEM cfg802154 | ||
| 5 | |||
| 6 | #if !defined(__RDEV_CFG802154_OPS_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
| 7 | #define __RDEV_CFG802154_OPS_TRACE | ||
| 8 | |||
| 9 | #include <linux/tracepoint.h> | ||
| 10 | |||
| 11 | #include <net/cfg802154.h> | ||
| 12 | |||
| 13 | #define MAXNAME 32 | ||
| 14 | #define WPAN_PHY_ENTRY __array(char, wpan_phy_name, MAXNAME) | ||
| 15 | #define WPAN_PHY_ASSIGN strlcpy(__entry->wpan_phy_name, \ | ||
| 16 | wpan_phy_name(wpan_phy), \ | ||
| 17 | MAXNAME) | ||
| 18 | #define WPAN_PHY_PR_FMT "%s" | ||
| 19 | #define WPAN_PHY_PR_ARG __entry->wpan_phy_name | ||
| 20 | |||
| 21 | #define WPAN_DEV_ENTRY __field(u32, identifier) | ||
| 22 | #define WPAN_DEV_ASSIGN (__entry->identifier) = (!IS_ERR_OR_NULL(wpan_dev) \ | ||
| 23 | ? wpan_dev->identifier : 0) | ||
| 24 | #define WPAN_DEV_PR_FMT "wpan_dev(%u)" | ||
| 25 | #define WPAN_DEV_PR_ARG (__entry->identifier) | ||
| 26 | |||
| 27 | #define WPAN_CCA_ENTRY __field(enum nl802154_cca_modes, cca_mode) \ | ||
| 28 | __field(enum nl802154_cca_opts, cca_opt) | ||
| 29 | #define WPAN_CCA_ASSIGN \ | ||
| 30 | do { \ | ||
| 31 | (__entry->cca_mode) = cca->mode; \ | ||
| 32 | (__entry->cca_opt) = cca->opt; \ | ||
| 33 | } while (0) | ||
| 34 | #define WPAN_CCA_PR_FMT "cca_mode: %d, cca_opt: %d" | ||
| 35 | #define WPAN_CCA_PR_ARG __entry->cca_mode, __entry->cca_opt | ||
| 36 | |||
| 37 | #define BOOL_TO_STR(bo) (bo) ? "true" : "false" | ||
| 38 | |||
| 39 | /************************************************************* | ||
| 40 | * rdev->ops traces * | ||
| 41 | *************************************************************/ | ||
| 42 | |||
| 43 | TRACE_EVENT(802154_rdev_add_virtual_intf, | ||
| 44 | TP_PROTO(struct wpan_phy *wpan_phy, char *name, | ||
| 45 | enum nl802154_iftype type, __le64 extended_addr), | ||
| 46 | TP_ARGS(wpan_phy, name, type, extended_addr), | ||
| 47 | TP_STRUCT__entry( | ||
| 48 | WPAN_PHY_ENTRY | ||
| 49 | __string(vir_intf_name, name ? name : "<noname>") | ||
| 50 | __field(enum nl802154_iftype, type) | ||
| 51 | __field(__le64, extended_addr) | ||
| 52 | ), | ||
| 53 | TP_fast_assign( | ||
| 54 | WPAN_PHY_ASSIGN; | ||
| 55 | __assign_str(vir_intf_name, name ? name : "<noname>"); | ||
| 56 | __entry->type = type; | ||
| 57 | __entry->extended_addr = extended_addr; | ||
| 58 | ), | ||
| 59 | TP_printk(WPAN_PHY_PR_FMT ", virtual intf name: %s, type: %d, ea %llx", | ||
| 60 | WPAN_PHY_PR_ARG, __get_str(vir_intf_name), __entry->type, | ||
| 61 | __le64_to_cpu(__entry->extended_addr)) | ||
| 62 | ); | ||
| 63 | |||
| 64 | TRACE_EVENT(802154_rdev_del_virtual_intf, | ||
| 65 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev), | ||
| 66 | TP_ARGS(wpan_phy, wpan_dev), | ||
| 67 | TP_STRUCT__entry( | ||
| 68 | WPAN_PHY_ENTRY | ||
| 69 | WPAN_DEV_ENTRY | ||
| 70 | ), | ||
| 71 | TP_fast_assign( | ||
| 72 | WPAN_PHY_ASSIGN; | ||
| 73 | WPAN_DEV_ASSIGN; | ||
| 74 | ), | ||
| 75 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT, WPAN_PHY_PR_ARG, | ||
| 76 | WPAN_DEV_PR_ARG) | ||
| 77 | ); | ||
| 78 | |||
| 79 | TRACE_EVENT(802154_rdev_set_channel, | ||
| 80 | TP_PROTO(struct wpan_phy *wpan_phy, u8 page, u8 channel), | ||
| 81 | TP_ARGS(wpan_phy, page, channel), | ||
| 82 | TP_STRUCT__entry( | ||
| 83 | WPAN_PHY_ENTRY | ||
| 84 | __field(u8, page) | ||
| 85 | __field(u8, channel) | ||
| 86 | ), | ||
| 87 | TP_fast_assign( | ||
| 88 | WPAN_PHY_ASSIGN; | ||
| 89 | __entry->page = page; | ||
| 90 | __entry->channel = channel; | ||
| 91 | ), | ||
| 92 | TP_printk(WPAN_PHY_PR_FMT ", page: %d, channel: %d", WPAN_PHY_PR_ARG, | ||
| 93 | __entry->page, __entry->channel) | ||
| 94 | ); | ||
| 95 | |||
| 96 | TRACE_EVENT(802154_rdev_set_cca_mode, | ||
| 97 | TP_PROTO(struct wpan_phy *wpan_phy, const struct wpan_phy_cca *cca), | ||
| 98 | TP_ARGS(wpan_phy, cca), | ||
| 99 | TP_STRUCT__entry( | ||
| 100 | WPAN_PHY_ENTRY | ||
| 101 | WPAN_CCA_ENTRY | ||
| 102 | ), | ||
| 103 | TP_fast_assign( | ||
| 104 | WPAN_PHY_ASSIGN; | ||
| 105 | WPAN_CCA_ASSIGN; | ||
| 106 | ), | ||
| 107 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_CCA_PR_FMT, WPAN_PHY_PR_ARG, | ||
| 108 | WPAN_CCA_PR_ARG) | ||
| 109 | ); | ||
| 110 | |||
| 111 | DECLARE_EVENT_CLASS(802154_le16_template, | ||
| 112 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 113 | __le16 le16arg), | ||
| 114 | TP_ARGS(wpan_phy, wpan_dev, le16arg), | ||
| 115 | TP_STRUCT__entry( | ||
| 116 | WPAN_PHY_ENTRY | ||
| 117 | WPAN_DEV_ENTRY | ||
| 118 | __field(__le16, le16arg) | ||
| 119 | ), | ||
| 120 | TP_fast_assign( | ||
| 121 | WPAN_PHY_ASSIGN; | ||
| 122 | WPAN_DEV_ASSIGN; | ||
| 123 | __entry->le16arg = le16arg; | ||
| 124 | ), | ||
| 125 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", pan id: 0x%04x", | ||
| 126 | WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, | ||
| 127 | __le16_to_cpu(__entry->le16arg)) | ||
| 128 | ); | ||
| 129 | |||
| 130 | DEFINE_EVENT(802154_le16_template, 802154_rdev_set_pan_id, | ||
| 131 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 132 | __le16 le16arg), | ||
| 133 | TP_ARGS(wpan_phy, wpan_dev, le16arg) | ||
| 134 | ); | ||
| 135 | |||
| 136 | DEFINE_EVENT_PRINT(802154_le16_template, 802154_rdev_set_short_addr, | ||
| 137 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 138 | __le16 le16arg), | ||
| 139 | TP_ARGS(wpan_phy, wpan_dev, le16arg), | ||
| 140 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", sa: 0x%04x", | ||
| 141 | WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, | ||
| 142 | __le16_to_cpu(__entry->le16arg)) | ||
| 143 | ); | ||
| 144 | |||
| 145 | TRACE_EVENT(802154_rdev_set_backoff_exponent, | ||
| 146 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 147 | u8 min_be, u8 max_be), | ||
| 148 | TP_ARGS(wpan_phy, wpan_dev, min_be, max_be), | ||
| 149 | TP_STRUCT__entry( | ||
| 150 | WPAN_PHY_ENTRY | ||
| 151 | WPAN_DEV_ENTRY | ||
| 152 | __field(u8, min_be) | ||
| 153 | __field(u8, max_be) | ||
| 154 | ), | ||
| 155 | TP_fast_assign( | ||
| 156 | WPAN_PHY_ASSIGN; | ||
| 157 | WPAN_DEV_ASSIGN; | ||
| 158 | __entry->min_be = min_be; | ||
| 159 | __entry->max_be = max_be; | ||
| 160 | ), | ||
| 161 | |||
| 162 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
| 163 | ", min be: %d, max_be: %d", WPAN_PHY_PR_ARG, | ||
| 164 | WPAN_DEV_PR_ARG, __entry->min_be, __entry->max_be) | ||
| 165 | ); | ||
| 166 | |||
| 167 | TRACE_EVENT(802154_rdev_set_csma_backoffs, | ||
| 168 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 169 | u8 max_csma_backoffs), | ||
| 170 | TP_ARGS(wpan_phy, wpan_dev, max_csma_backoffs), | ||
| 171 | TP_STRUCT__entry( | ||
| 172 | WPAN_PHY_ENTRY | ||
| 173 | WPAN_DEV_ENTRY | ||
| 174 | __field(u8, max_csma_backoffs) | ||
| 175 | ), | ||
| 176 | TP_fast_assign( | ||
| 177 | WPAN_PHY_ASSIGN; | ||
| 178 | WPAN_DEV_ASSIGN; | ||
| 179 | __entry->max_csma_backoffs = max_csma_backoffs; | ||
| 180 | ), | ||
| 181 | |||
| 182 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
| 183 | ", max csma backoffs: %d", WPAN_PHY_PR_ARG, | ||
| 184 | WPAN_DEV_PR_ARG, __entry->max_csma_backoffs) | ||
| 185 | ); | ||
| 186 | |||
| 187 | TRACE_EVENT(802154_rdev_set_max_frame_retries, | ||
| 188 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 189 | s8 max_frame_retries), | ||
| 190 | TP_ARGS(wpan_phy, wpan_dev, max_frame_retries), | ||
| 191 | TP_STRUCT__entry( | ||
| 192 | WPAN_PHY_ENTRY | ||
| 193 | WPAN_DEV_ENTRY | ||
| 194 | __field(s8, max_frame_retries) | ||
| 195 | ), | ||
| 196 | TP_fast_assign( | ||
| 197 | WPAN_PHY_ASSIGN; | ||
| 198 | WPAN_DEV_ASSIGN; | ||
| 199 | __entry->max_frame_retries = max_frame_retries; | ||
| 200 | ), | ||
| 201 | |||
| 202 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
| 203 | ", max frame retries: %d", WPAN_PHY_PR_ARG, | ||
| 204 | WPAN_DEV_PR_ARG, __entry->max_frame_retries) | ||
| 205 | ); | ||
| 206 | |||
| 207 | TRACE_EVENT(802154_rdev_set_lbt_mode, | ||
| 208 | TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, | ||
| 209 | bool mode), | ||
| 210 | TP_ARGS(wpan_phy, wpan_dev, mode), | ||
| 211 | TP_STRUCT__entry( | ||
| 212 | WPAN_PHY_ENTRY | ||
| 213 | WPAN_DEV_ENTRY | ||
| 214 | __field(bool, mode) | ||
| 215 | ), | ||
| 216 | TP_fast_assign( | ||
| 217 | WPAN_PHY_ASSIGN; | ||
| 218 | WPAN_DEV_ASSIGN; | ||
| 219 | __entry->mode = mode; | ||
| 220 | ), | ||
| 221 | TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT | ||
| 222 | ", lbt mode: %s", WPAN_PHY_PR_ARG, | ||
| 223 | WPAN_DEV_PR_ARG, BOOL_TO_STR(__entry->mode)) | ||
| 224 | ); | ||
| 225 | |||
| 226 | TRACE_EVENT(802154_rdev_return_int, | ||
| 227 | TP_PROTO(struct wpan_phy *wpan_phy, int ret), | ||
| 228 | TP_ARGS(wpan_phy, ret), | ||
| 229 | TP_STRUCT__entry( | ||
| 230 | WPAN_PHY_ENTRY | ||
| 231 | __field(int, ret) | ||
| 232 | ), | ||
| 233 | TP_fast_assign( | ||
| 234 | WPAN_PHY_ASSIGN; | ||
| 235 | __entry->ret = ret; | ||
| 236 | ), | ||
| 237 | TP_printk(WPAN_PHY_PR_FMT ", returned: %d", WPAN_PHY_PR_ARG, | ||
| 238 | __entry->ret) | ||
| 239 | ); | ||
| 240 | |||
| 241 | #endif /* !__RDEV_CFG802154_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | ||
| 242 | |||
| 243 | #undef TRACE_INCLUDE_PATH | ||
| 244 | #define TRACE_INCLUDE_PATH . | ||
| 245 | #undef TRACE_INCLUDE_FILE | ||
| 246 | #define TRACE_INCLUDE_FILE trace | ||
| 247 | #include <trace/define_trace.h> | ||
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 421a80b09b62..30b544f025ac 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
| @@ -256,7 +256,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 256 | aead_givcrypt_set_crypt(req, sg, sg, clen, iv); | 256 | aead_givcrypt_set_crypt(req, sg, sg, clen, iv); |
| 257 | aead_givcrypt_set_assoc(req, asg, assoclen); | 257 | aead_givcrypt_set_assoc(req, asg, assoclen); |
| 258 | aead_givcrypt_set_giv(req, esph->enc_data, | 258 | aead_givcrypt_set_giv(req, esph->enc_data, |
| 259 | XFRM_SKB_CB(skb)->seq.output.low); | 259 | XFRM_SKB_CB(skb)->seq.output.low + |
| 260 | ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32)); | ||
| 260 | 261 | ||
| 261 | ESP_SKB_CB(skb)->tmp = tmp; | 262 | ESP_SKB_CB(skb)->tmp = tmp; |
| 262 | err = crypto_aead_givencrypt(req); | 263 | err = crypto_aead_givencrypt(req); |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index e13fcc602da2..09b62e17dd8c 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -1164,6 +1164,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
| 1164 | state = fa->fa_state; | 1164 | state = fa->fa_state; |
| 1165 | new_fa->fa_state = state & ~FA_S_ACCESSED; | 1165 | new_fa->fa_state = state & ~FA_S_ACCESSED; |
| 1166 | new_fa->fa_slen = fa->fa_slen; | 1166 | new_fa->fa_slen = fa->fa_slen; |
| 1167 | new_fa->tb_id = tb->tb_id; | ||
| 1167 | 1168 | ||
| 1168 | err = netdev_switch_fib_ipv4_add(key, plen, fi, | 1169 | err = netdev_switch_fib_ipv4_add(key, plen, fi, |
| 1169 | new_fa->fa_tos, | 1170 | new_fa->fa_tos, |
| @@ -1764,7 +1765,7 @@ void fib_table_flush_external(struct fib_table *tb) | |||
| 1764 | /* record local slen */ | 1765 | /* record local slen */ |
| 1765 | slen = fa->fa_slen; | 1766 | slen = fa->fa_slen; |
| 1766 | 1767 | ||
| 1767 | if (!fi || !(fi->fib_flags & RTNH_F_EXTERNAL)) | 1768 | if (!fi || !(fi->fib_flags & RTNH_F_OFFLOAD)) |
| 1768 | continue; | 1769 | continue; |
| 1769 | 1770 | ||
| 1770 | netdev_switch_fib_ipv4_del(n->key, | 1771 | netdev_switch_fib_ipv4_del(n->key, |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 5c3dd6267ed3..8976ca423a07 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
| @@ -564,6 +564,40 @@ int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req) | |||
| 564 | } | 564 | } |
| 565 | EXPORT_SYMBOL(inet_rtx_syn_ack); | 565 | EXPORT_SYMBOL(inet_rtx_syn_ack); |
| 566 | 566 | ||
| 567 | /* return true if req was found in the syn_table[] */ | ||
| 568 | static bool reqsk_queue_unlink(struct request_sock_queue *queue, | ||
| 569 | struct request_sock *req) | ||
| 570 | { | ||
| 571 | struct listen_sock *lopt = queue->listen_opt; | ||
| 572 | struct request_sock **prev; | ||
| 573 | bool found = false; | ||
| 574 | |||
| 575 | spin_lock(&queue->syn_wait_lock); | ||
| 576 | |||
| 577 | for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL; | ||
| 578 | prev = &(*prev)->dl_next) { | ||
| 579 | if (*prev == req) { | ||
| 580 | *prev = req->dl_next; | ||
| 581 | found = true; | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 586 | spin_unlock(&queue->syn_wait_lock); | ||
| 587 | if (del_timer(&req->rsk_timer)) | ||
| 588 | reqsk_put(req); | ||
| 589 | return found; | ||
| 590 | } | ||
| 591 | |||
| 592 | void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req) | ||
| 593 | { | ||
| 594 | if (reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req)) { | ||
| 595 | reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req); | ||
| 596 | reqsk_put(req); | ||
| 597 | } | ||
| 598 | } | ||
| 599 | EXPORT_SYMBOL(inet_csk_reqsk_queue_drop); | ||
| 600 | |||
| 567 | static void reqsk_timer_handler(unsigned long data) | 601 | static void reqsk_timer_handler(unsigned long data) |
| 568 | { | 602 | { |
| 569 | struct request_sock *req = (struct request_sock *)data; | 603 | struct request_sock *req = (struct request_sock *)data; |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index bb77ebdae3b3..4d32262c7502 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
| @@ -224,14 +224,16 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | |||
| 224 | handler->idiag_get_info(sk, r, info); | 224 | handler->idiag_get_info(sk, r, info); |
| 225 | 225 | ||
| 226 | if (sk->sk_state < TCP_TIME_WAIT) { | 226 | if (sk->sk_state < TCP_TIME_WAIT) { |
| 227 | int err = 0; | 227 | union tcp_cc_info info; |
| 228 | size_t sz = 0; | ||
| 229 | int attr; | ||
| 228 | 230 | ||
| 229 | rcu_read_lock(); | 231 | rcu_read_lock(); |
| 230 | ca_ops = READ_ONCE(icsk->icsk_ca_ops); | 232 | ca_ops = READ_ONCE(icsk->icsk_ca_ops); |
| 231 | if (ca_ops && ca_ops->get_info) | 233 | if (ca_ops && ca_ops->get_info) |
| 232 | err = ca_ops->get_info(sk, ext, skb); | 234 | sz = ca_ops->get_info(sk, ext, &attr, &info); |
| 233 | rcu_read_unlock(); | 235 | rcu_read_unlock(); |
| 234 | if (err < 0) | 236 | if (sz && nla_put(skb, attr, sz, &info) < 0) |
| 235 | goto errout; | 237 | goto errout; |
| 236 | } | 238 | } |
| 237 | 239 | ||
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 9f7269f3c54a..0c152087ca15 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
| @@ -65,7 +65,6 @@ static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi, | |||
| 65 | goto drop; | 65 | goto drop; |
| 66 | 66 | ||
| 67 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel; | 67 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel; |
| 68 | skb->mark = be32_to_cpu(tunnel->parms.i_key); | ||
| 69 | 68 | ||
| 70 | return xfrm_input(skb, nexthdr, spi, encap_type); | 69 | return xfrm_input(skb, nexthdr, spi, encap_type); |
| 71 | } | 70 | } |
| @@ -91,6 +90,8 @@ static int vti_rcv_cb(struct sk_buff *skb, int err) | |||
| 91 | struct pcpu_sw_netstats *tstats; | 90 | struct pcpu_sw_netstats *tstats; |
| 92 | struct xfrm_state *x; | 91 | struct xfrm_state *x; |
| 93 | struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; | 92 | struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; |
| 93 | u32 orig_mark = skb->mark; | ||
| 94 | int ret; | ||
| 94 | 95 | ||
| 95 | if (!tunnel) | 96 | if (!tunnel) |
| 96 | return 1; | 97 | return 1; |
| @@ -107,7 +108,11 @@ static int vti_rcv_cb(struct sk_buff *skb, int err) | |||
| 107 | x = xfrm_input_state(skb); | 108 | x = xfrm_input_state(skb); |
| 108 | family = x->inner_mode->afinfo->family; | 109 | family = x->inner_mode->afinfo->family; |
| 109 | 110 | ||
| 110 | if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) | 111 | skb->mark = be32_to_cpu(tunnel->parms.i_key); |
| 112 | ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); | ||
| 113 | skb->mark = orig_mark; | ||
| 114 | |||
| 115 | if (!ret) | ||
| 111 | return -EPERM; | 116 | return -EPERM; |
| 112 | 117 | ||
| 113 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev))); | 118 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev))); |
| @@ -216,8 +221,6 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 216 | 221 | ||
| 217 | memset(&fl, 0, sizeof(fl)); | 222 | memset(&fl, 0, sizeof(fl)); |
| 218 | 223 | ||
| 219 | skb->mark = be32_to_cpu(tunnel->parms.o_key); | ||
| 220 | |||
| 221 | switch (skb->protocol) { | 224 | switch (skb->protocol) { |
| 222 | case htons(ETH_P_IP): | 225 | case htons(ETH_P_IP): |
| 223 | xfrm_decode_session(skb, &fl, AF_INET); | 226 | xfrm_decode_session(skb, &fl, AF_INET); |
| @@ -233,6 +236,9 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 233 | return NETDEV_TX_OK; | 236 | return NETDEV_TX_OK; |
| 234 | } | 237 | } |
| 235 | 238 | ||
| 239 | /* override mark with tunnel output key */ | ||
| 240 | fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key); | ||
| 241 | |||
| 236 | return vti_xmit(skb, dev, &fl); | 242 | return vti_xmit(skb, dev, &fl); |
| 237 | } | 243 | } |
| 238 | 244 | ||
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 13bfe84bf3ca..a61200754f4b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
| @@ -1075,6 +1075,9 @@ static int do_replace(struct net *net, const void __user *user, | |||
| 1075 | /* overflow check */ | 1075 | /* overflow check */ |
| 1076 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1076 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
| 1077 | return -ENOMEM; | 1077 | return -ENOMEM; |
| 1078 | if (tmp.num_counters == 0) | ||
| 1079 | return -EINVAL; | ||
| 1080 | |||
| 1078 | tmp.name[sizeof(tmp.name)-1] = 0; | 1081 | tmp.name[sizeof(tmp.name)-1] = 0; |
| 1079 | 1082 | ||
| 1080 | newinfo = xt_alloc_table_info(tmp.size); | 1083 | newinfo = xt_alloc_table_info(tmp.size); |
| @@ -1499,6 +1502,9 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
| 1499 | return -ENOMEM; | 1502 | return -ENOMEM; |
| 1500 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1503 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
| 1501 | return -ENOMEM; | 1504 | return -ENOMEM; |
| 1505 | if (tmp.num_counters == 0) | ||
| 1506 | return -EINVAL; | ||
| 1507 | |||
| 1502 | tmp.name[sizeof(tmp.name)-1] = 0; | 1508 | tmp.name[sizeof(tmp.name)-1] = 0; |
| 1503 | 1509 | ||
| 1504 | newinfo = xt_alloc_table_info(tmp.size); | 1510 | newinfo = xt_alloc_table_info(tmp.size); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index c69db7fa25ee..2d0e265fef6e 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
| @@ -1262,6 +1262,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
| 1262 | /* overflow check */ | 1262 | /* overflow check */ |
| 1263 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1263 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
| 1264 | return -ENOMEM; | 1264 | return -ENOMEM; |
| 1265 | if (tmp.num_counters == 0) | ||
| 1266 | return -EINVAL; | ||
| 1267 | |||
| 1265 | tmp.name[sizeof(tmp.name)-1] = 0; | 1268 | tmp.name[sizeof(tmp.name)-1] = 0; |
| 1266 | 1269 | ||
| 1267 | newinfo = xt_alloc_table_info(tmp.size); | 1270 | newinfo = xt_alloc_table_info(tmp.size); |
| @@ -1809,6 +1812,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
| 1809 | return -ENOMEM; | 1812 | return -ENOMEM; |
| 1810 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1813 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
| 1811 | return -ENOMEM; | 1814 | return -ENOMEM; |
| 1815 | if (tmp.num_counters == 0) | ||
| 1816 | return -EINVAL; | ||
| 1817 | |||
| 1812 | tmp.name[sizeof(tmp.name)-1] = 0; | 1818 | tmp.name[sizeof(tmp.name)-1] = 0; |
| 1813 | 1819 | ||
| 1814 | newinfo = xt_alloc_table_info(tmp.size); | 1820 | newinfo = xt_alloc_table_info(tmp.size); |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index a93f260cf24c..05ff44b758df 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
| @@ -158,6 +158,7 @@ void ping_unhash(struct sock *sk) | |||
| 158 | if (sk_hashed(sk)) { | 158 | if (sk_hashed(sk)) { |
| 159 | write_lock_bh(&ping_table.lock); | 159 | write_lock_bh(&ping_table.lock); |
| 160 | hlist_nulls_del(&sk->sk_nulls_node); | 160 | hlist_nulls_del(&sk->sk_nulls_node); |
| 161 | sk_nulls_node_init(&sk->sk_nulls_node); | ||
| 161 | sock_put(sk); | 162 | sock_put(sk); |
| 162 | isk->inet_num = 0; | 163 | isk->inet_num = 0; |
| 163 | isk->inet_sport = 0; | 164 | isk->inet_sport = 0; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index a78540f28276..f45f2a12f37b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -902,6 +902,10 @@ static int ip_error(struct sk_buff *skb) | |||
| 902 | bool send; | 902 | bool send; |
| 903 | int code; | 903 | int code; |
| 904 | 904 | ||
| 905 | /* IP on this device is disabled. */ | ||
| 906 | if (!in_dev) | ||
| 907 | goto out; | ||
| 908 | |||
| 905 | net = dev_net(rt->dst.dev); | 909 | net = dev_net(rt->dst.dev); |
| 906 | if (!IN_DEV_FORWARD(in_dev)) { | 910 | if (!IN_DEV_FORWARD(in_dev)) { |
| 907 | switch (rt->dst.error) { | 911 | switch (rt->dst.error) { |
| @@ -962,10 +966,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) | |||
| 962 | if (dst_metric_locked(dst, RTAX_MTU)) | 966 | if (dst_metric_locked(dst, RTAX_MTU)) |
| 963 | return; | 967 | return; |
| 964 | 968 | ||
| 965 | if (dst->dev->mtu < mtu) | 969 | if (ipv4_mtu(dst) < mtu) |
| 966 | return; | ||
| 967 | |||
| 968 | if (rt->rt_pmtu && rt->rt_pmtu < mtu) | ||
| 969 | return; | 970 | return; |
| 970 | 971 | ||
| 971 | if (mtu < ip_rt_min_pmtu) | 972 | if (mtu < ip_rt_min_pmtu) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8c5cd9efebbc..f1377f2a0472 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -252,6 +252,7 @@ | |||
| 252 | #include <linux/types.h> | 252 | #include <linux/types.h> |
| 253 | #include <linux/fcntl.h> | 253 | #include <linux/fcntl.h> |
| 254 | #include <linux/poll.h> | 254 | #include <linux/poll.h> |
| 255 | #include <linux/inet_diag.h> | ||
| 255 | #include <linux/init.h> | 256 | #include <linux/init.h> |
| 256 | #include <linux/fs.h> | 257 | #include <linux/fs.h> |
| 257 | #include <linux/skbuff.h> | 258 | #include <linux/skbuff.h> |
| @@ -401,6 +402,7 @@ void tcp_init_sock(struct sock *sk) | |||
| 401 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; | 402 | tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; |
| 402 | tp->snd_cwnd_clamp = ~0; | 403 | tp->snd_cwnd_clamp = ~0; |
| 403 | tp->mss_cache = TCP_MSS_DEFAULT; | 404 | tp->mss_cache = TCP_MSS_DEFAULT; |
| 405 | u64_stats_init(&tp->syncp); | ||
| 404 | 406 | ||
| 405 | tp->reordering = sysctl_tcp_reordering; | 407 | tp->reordering = sysctl_tcp_reordering; |
| 406 | tcp_enable_early_retrans(tp); | 408 | tcp_enable_early_retrans(tp); |
| @@ -2592,11 +2594,12 @@ EXPORT_SYMBOL(compat_tcp_setsockopt); | |||
| 2592 | #endif | 2594 | #endif |
| 2593 | 2595 | ||
| 2594 | /* Return information about state of tcp endpoint in API format. */ | 2596 | /* Return information about state of tcp endpoint in API format. */ |
| 2595 | void tcp_get_info(const struct sock *sk, struct tcp_info *info) | 2597 | void tcp_get_info(struct sock *sk, struct tcp_info *info) |
| 2596 | { | 2598 | { |
| 2597 | const struct tcp_sock *tp = tcp_sk(sk); | 2599 | const struct tcp_sock *tp = tcp_sk(sk); |
| 2598 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2600 | const struct inet_connection_sock *icsk = inet_csk(sk); |
| 2599 | u32 now = tcp_time_stamp; | 2601 | u32 now = tcp_time_stamp; |
| 2602 | unsigned int start; | ||
| 2600 | u32 rate; | 2603 | u32 rate; |
| 2601 | 2604 | ||
| 2602 | memset(info, 0, sizeof(*info)); | 2605 | memset(info, 0, sizeof(*info)); |
| @@ -2663,6 +2666,12 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
| 2663 | 2666 | ||
| 2664 | rate = READ_ONCE(sk->sk_max_pacing_rate); | 2667 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
| 2665 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2668 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; |
| 2669 | |||
| 2670 | do { | ||
| 2671 | start = u64_stats_fetch_begin_irq(&tp->syncp); | ||
| 2672 | info->tcpi_bytes_acked = tp->bytes_acked; | ||
| 2673 | info->tcpi_bytes_received = tp->bytes_received; | ||
| 2674 | } while (u64_stats_fetch_retry_irq(&tp->syncp, start)); | ||
| 2666 | } | 2675 | } |
| 2667 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2676 | EXPORT_SYMBOL_GPL(tcp_get_info); |
| 2668 | 2677 | ||
| @@ -2734,6 +2743,26 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
| 2734 | return -EFAULT; | 2743 | return -EFAULT; |
| 2735 | return 0; | 2744 | return 0; |
| 2736 | } | 2745 | } |
| 2746 | case TCP_CC_INFO: { | ||
| 2747 | const struct tcp_congestion_ops *ca_ops; | ||
| 2748 | union tcp_cc_info info; | ||
| 2749 | size_t sz = 0; | ||
| 2750 | int attr; | ||
| 2751 | |||
| 2752 | if (get_user(len, optlen)) | ||
| 2753 | return -EFAULT; | ||
| 2754 | |||
| 2755 | ca_ops = icsk->icsk_ca_ops; | ||
| 2756 | if (ca_ops && ca_ops->get_info) | ||
| 2757 | sz = ca_ops->get_info(sk, ~0U, &attr, &info); | ||
| 2758 | |||
| 2759 | len = min_t(unsigned int, len, sz); | ||
| 2760 | if (put_user(len, optlen)) | ||
| 2761 | return -EFAULT; | ||
| 2762 | if (copy_to_user(optval, &info, len)) | ||
| 2763 | return -EFAULT; | ||
| 2764 | return 0; | ||
| 2765 | } | ||
| 2737 | case TCP_QUICKACK: | 2766 | case TCP_QUICKACK: |
| 2738 | val = !icsk->icsk_ack.pingpong; | 2767 | val = !icsk->icsk_ack.pingpong; |
| 2739 | break; | 2768 | break; |
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 7a5ae50c80c8..84be008c945c 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -187,6 +187,7 @@ static void tcp_reinit_congestion_control(struct sock *sk, | |||
| 187 | 187 | ||
| 188 | tcp_cleanup_congestion_control(sk); | 188 | tcp_cleanup_congestion_control(sk); |
| 189 | icsk->icsk_ca_ops = ca; | 189 | icsk->icsk_ca_ops = ca; |
| 190 | icsk->icsk_ca_setsockopt = 1; | ||
| 190 | 191 | ||
| 191 | if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) | 192 | if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) |
| 192 | icsk->icsk_ca_ops->init(sk); | 193 | icsk->icsk_ca_ops->init(sk); |
| @@ -335,8 +336,10 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
| 335 | rcu_read_lock(); | 336 | rcu_read_lock(); |
| 336 | ca = __tcp_ca_find_autoload(name); | 337 | ca = __tcp_ca_find_autoload(name); |
| 337 | /* No change asking for existing value */ | 338 | /* No change asking for existing value */ |
| 338 | if (ca == icsk->icsk_ca_ops) | 339 | if (ca == icsk->icsk_ca_ops) { |
| 340 | icsk->icsk_ca_setsockopt = 1; | ||
| 339 | goto out; | 341 | goto out; |
| 342 | } | ||
| 340 | if (!ca) | 343 | if (!ca) |
| 341 | err = -ENOENT; | 344 | err = -ENOENT; |
| 342 | else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || | 345 | else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || |
diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c index 4376016f7fa5..4c41c1287197 100644 --- a/net/ipv4/tcp_dctcp.c +++ b/net/ipv4/tcp_dctcp.c | |||
| @@ -277,7 +277,8 @@ static void dctcp_cwnd_event(struct sock *sk, enum tcp_ca_event ev) | |||
| 277 | } | 277 | } |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | static int dctcp_get_info(struct sock *sk, u32 ext, struct sk_buff *skb) | 280 | static size_t dctcp_get_info(struct sock *sk, u32 ext, int *attr, |
| 281 | union tcp_cc_info *info) | ||
| 281 | { | 282 | { |
| 282 | const struct dctcp *ca = inet_csk_ca(sk); | 283 | const struct dctcp *ca = inet_csk_ca(sk); |
| 283 | 284 | ||
| @@ -286,18 +287,17 @@ static int dctcp_get_info(struct sock *sk, u32 ext, struct sk_buff *skb) | |||
| 286 | */ | 287 | */ |
| 287 | if (ext & (1 << (INET_DIAG_DCTCPINFO - 1)) || | 288 | if (ext & (1 << (INET_DIAG_DCTCPINFO - 1)) || |
| 288 | ext & (1 << (INET_DIAG_VEGASINFO - 1))) { | 289 | ext & (1 << (INET_DIAG_VEGASINFO - 1))) { |
| 289 | struct tcp_dctcp_info info; | 290 | memset(info, 0, sizeof(struct tcp_dctcp_info)); |
| 290 | |||
| 291 | memset(&info, 0, sizeof(info)); | ||
| 292 | if (inet_csk(sk)->icsk_ca_ops != &dctcp_reno) { | 291 | if (inet_csk(sk)->icsk_ca_ops != &dctcp_reno) { |
| 293 | info.dctcp_enabled = 1; | 292 | info->dctcp.dctcp_enabled = 1; |
| 294 | info.dctcp_ce_state = (u16) ca->ce_state; | 293 | info->dctcp.dctcp_ce_state = (u16) ca->ce_state; |
| 295 | info.dctcp_alpha = ca->dctcp_alpha; | 294 | info->dctcp.dctcp_alpha = ca->dctcp_alpha; |
| 296 | info.dctcp_ab_ecn = ca->acked_bytes_ecn; | 295 | info->dctcp.dctcp_ab_ecn = ca->acked_bytes_ecn; |
| 297 | info.dctcp_ab_tot = ca->acked_bytes_total; | 296 | info->dctcp.dctcp_ab_tot = ca->acked_bytes_total; |
| 298 | } | 297 | } |
| 299 | 298 | ||
| 300 | return nla_put(skb, INET_DIAG_DCTCPINFO, sizeof(info), &info); | 299 | *attr = INET_DIAG_DCTCPINFO; |
| 300 | return sizeof(*info); | ||
| 301 | } | 301 | } |
| 302 | return 0; | 302 | return 0; |
| 303 | } | 303 | } |
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index e3d87aca6be8..46b087a27503 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
| @@ -206,6 +206,11 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 206 | skb_set_owner_r(skb2, child); | 206 | skb_set_owner_r(skb2, child); |
| 207 | __skb_queue_tail(&child->sk_receive_queue, skb2); | 207 | __skb_queue_tail(&child->sk_receive_queue, skb2); |
| 208 | tp->syn_data_acked = 1; | 208 | tp->syn_data_acked = 1; |
| 209 | |||
| 210 | /* u64_stats_update_begin(&tp->syncp) not needed here, | ||
| 211 | * as we certainly are not changing upper 32bit value (0) | ||
| 212 | */ | ||
| 213 | tp->bytes_received = end_seq - TCP_SKB_CB(skb)->seq - 1; | ||
| 209 | } else { | 214 | } else { |
| 210 | end_seq = TCP_SKB_CB(skb)->seq + 1; | 215 | end_seq = TCP_SKB_CB(skb)->seq + 1; |
| 211 | } | 216 | } |
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 67476f085e48..f71002e4db0b 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c | |||
| @@ -300,24 +300,25 @@ static u32 tcp_illinois_ssthresh(struct sock *sk) | |||
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | /* Extract info for Tcp socket info provided via netlink. */ | 302 | /* Extract info for Tcp socket info provided via netlink. */ |
| 303 | static int tcp_illinois_info(struct sock *sk, u32 ext, struct sk_buff *skb) | 303 | static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr, |
| 304 | union tcp_cc_info *info) | ||
| 304 | { | 305 | { |
| 305 | const struct illinois *ca = inet_csk_ca(sk); | 306 | const struct illinois *ca = inet_csk_ca(sk); |
| 306 | 307 | ||
| 307 | if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) { | 308 | if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) { |
| 308 | struct tcpvegas_info info = { | 309 | info->vegas.tcpv_enabled = 1; |
| 309 | .tcpv_enabled = 1, | 310 | info->vegas.tcpv_rttcnt = ca->cnt_rtt; |
| 310 | .tcpv_rttcnt = ca->cnt_rtt, | 311 | info->vegas.tcpv_minrtt = ca->base_rtt; |
| 311 | .tcpv_minrtt = ca->base_rtt, | 312 | info->vegas.tcpv_rtt = 0; |
| 312 | }; | ||
| 313 | 313 | ||
| 314 | if (info.tcpv_rttcnt > 0) { | 314 | if (info->vegas.tcpv_rttcnt > 0) { |
| 315 | u64 t = ca->sum_rtt; | 315 | u64 t = ca->sum_rtt; |
| 316 | 316 | ||
| 317 | do_div(t, info.tcpv_rttcnt); | 317 | do_div(t, info->vegas.tcpv_rttcnt); |
| 318 | info.tcpv_rtt = t; | 318 | info->vegas.tcpv_rtt = t; |
| 319 | } | 319 | } |
| 320 | return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); | 320 | *attr = INET_DIAG_VEGASINFO; |
| 321 | return sizeof(struct tcpvegas_info); | ||
| 321 | } | 322 | } |
| 322 | return 0; | 323 | return 0; |
| 323 | } | 324 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3a4d9b34bed4..c9ab964189a0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1820,14 +1820,12 @@ advance_sp: | |||
| 1820 | for (j = 0; j < used_sacks; j++) | 1820 | for (j = 0; j < used_sacks; j++) |
| 1821 | tp->recv_sack_cache[i++] = sp[j]; | 1821 | tp->recv_sack_cache[i++] = sp[j]; |
| 1822 | 1822 | ||
| 1823 | tcp_mark_lost_retrans(sk); | ||
| 1824 | |||
| 1825 | tcp_verify_left_out(tp); | ||
| 1826 | |||
| 1827 | if ((state.reord < tp->fackets_out) && | 1823 | if ((state.reord < tp->fackets_out) && |
| 1828 | ((inet_csk(sk)->icsk_ca_state != TCP_CA_Loss) || tp->undo_marker)) | 1824 | ((inet_csk(sk)->icsk_ca_state != TCP_CA_Loss) || tp->undo_marker)) |
| 1829 | tcp_update_reordering(sk, tp->fackets_out - state.reord, 0); | 1825 | tcp_update_reordering(sk, tp->fackets_out - state.reord, 0); |
| 1830 | 1826 | ||
| 1827 | tcp_mark_lost_retrans(sk); | ||
| 1828 | tcp_verify_left_out(tp); | ||
| 1831 | out: | 1829 | out: |
| 1832 | 1830 | ||
| 1833 | #if FASTRETRANS_DEBUG > 0 | 1831 | #if FASTRETRANS_DEBUG > 0 |
| @@ -2700,16 +2698,21 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
| 2700 | struct tcp_sock *tp = tcp_sk(sk); | 2698 | struct tcp_sock *tp = tcp_sk(sk); |
| 2701 | bool recovered = !before(tp->snd_una, tp->high_seq); | 2699 | bool recovered = !before(tp->snd_una, tp->high_seq); |
| 2702 | 2700 | ||
| 2701 | if ((flag & FLAG_SND_UNA_ADVANCED) && | ||
| 2702 | tcp_try_undo_loss(sk, false)) | ||
| 2703 | return; | ||
| 2704 | |||
| 2703 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ | 2705 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ |
| 2704 | /* Step 3.b. A timeout is spurious if not all data are | 2706 | /* Step 3.b. A timeout is spurious if not all data are |
| 2705 | * lost, i.e., never-retransmitted data are (s)acked. | 2707 | * lost, i.e., never-retransmitted data are (s)acked. |
| 2706 | */ | 2708 | */ |
| 2707 | if (tcp_try_undo_loss(sk, flag & FLAG_ORIG_SACK_ACKED)) | 2709 | if ((flag & FLAG_ORIG_SACK_ACKED) && |
| 2710 | tcp_try_undo_loss(sk, true)) | ||
| 2708 | return; | 2711 | return; |
| 2709 | 2712 | ||
| 2710 | if (after(tp->snd_nxt, tp->high_seq) && | 2713 | if (after(tp->snd_nxt, tp->high_seq)) { |
| 2711 | (flag & FLAG_DATA_SACKED || is_dupack)) { | 2714 | if (flag & FLAG_DATA_SACKED || is_dupack) |
| 2712 | tp->frto = 0; /* Loss was real: 2nd part of step 3.a */ | 2715 | tp->frto = 0; /* Step 3.a. loss was real */ |
| 2713 | } else if (flag & FLAG_SND_UNA_ADVANCED && !recovered) { | 2716 | } else if (flag & FLAG_SND_UNA_ADVANCED && !recovered) { |
| 2714 | tp->high_seq = tp->snd_nxt; | 2717 | tp->high_seq = tp->snd_nxt; |
| 2715 | __tcp_push_pending_frames(sk, tcp_current_mss(sk), | 2718 | __tcp_push_pending_frames(sk, tcp_current_mss(sk), |
| @@ -2734,8 +2737,6 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
| 2734 | else if (flag & FLAG_SND_UNA_ADVANCED) | 2737 | else if (flag & FLAG_SND_UNA_ADVANCED) |
| 2735 | tcp_reset_reno_sack(tp); | 2738 | tcp_reset_reno_sack(tp); |
| 2736 | } | 2739 | } |
| 2737 | if (tcp_try_undo_loss(sk, false)) | ||
| 2738 | return; | ||
| 2739 | tcp_xmit_retransmit_queue(sk); | 2740 | tcp_xmit_retransmit_queue(sk); |
| 2740 | } | 2741 | } |
| 2741 | 2742 | ||
| @@ -3280,6 +3281,28 @@ static inline bool tcp_may_update_window(const struct tcp_sock *tp, | |||
| 3280 | (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd); | 3281 | (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd); |
| 3281 | } | 3282 | } |
| 3282 | 3283 | ||
| 3284 | /* If we update tp->snd_una, also update tp->bytes_acked */ | ||
| 3285 | static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) | ||
| 3286 | { | ||
| 3287 | u32 delta = ack - tp->snd_una; | ||
| 3288 | |||
| 3289 | u64_stats_update_begin(&tp->syncp); | ||
| 3290 | tp->bytes_acked += delta; | ||
| 3291 | u64_stats_update_end(&tp->syncp); | ||
| 3292 | tp->snd_una = ack; | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | /* If we update tp->rcv_nxt, also update tp->bytes_received */ | ||
| 3296 | static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq) | ||
| 3297 | { | ||
| 3298 | u32 delta = seq - tp->rcv_nxt; | ||
| 3299 | |||
| 3300 | u64_stats_update_begin(&tp->syncp); | ||
| 3301 | tp->bytes_received += delta; | ||
| 3302 | u64_stats_update_end(&tp->syncp); | ||
| 3303 | tp->rcv_nxt = seq; | ||
| 3304 | } | ||
| 3305 | |||
| 3283 | /* Update our send window. | 3306 | /* Update our send window. |
| 3284 | * | 3307 | * |
| 3285 | * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2 | 3308 | * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2 |
| @@ -3315,7 +3338,7 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 | |||
| 3315 | } | 3338 | } |
| 3316 | } | 3339 | } |
| 3317 | 3340 | ||
| 3318 | tp->snd_una = ack; | 3341 | tcp_snd_una_update(tp, ack); |
| 3319 | 3342 | ||
| 3320 | return flag; | 3343 | return flag; |
| 3321 | } | 3344 | } |
| @@ -3497,7 +3520,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3497 | * Note, we use the fact that SND.UNA>=SND.WL2. | 3520 | * Note, we use the fact that SND.UNA>=SND.WL2. |
| 3498 | */ | 3521 | */ |
| 3499 | tcp_update_wl(tp, ack_seq); | 3522 | tcp_update_wl(tp, ack_seq); |
| 3500 | tp->snd_una = ack; | 3523 | tcp_snd_una_update(tp, ack); |
| 3501 | flag |= FLAG_WIN_UPDATE; | 3524 | flag |= FLAG_WIN_UPDATE; |
| 3502 | 3525 | ||
| 3503 | tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); | 3526 | tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); |
| @@ -4236,7 +4259,7 @@ static void tcp_ofo_queue(struct sock *sk) | |||
| 4236 | 4259 | ||
| 4237 | tail = skb_peek_tail(&sk->sk_receive_queue); | 4260 | tail = skb_peek_tail(&sk->sk_receive_queue); |
| 4238 | eaten = tail && tcp_try_coalesce(sk, tail, skb, &fragstolen); | 4261 | eaten = tail && tcp_try_coalesce(sk, tail, skb, &fragstolen); |
| 4239 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 4262 | tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq); |
| 4240 | if (!eaten) | 4263 | if (!eaten) |
| 4241 | __skb_queue_tail(&sk->sk_receive_queue, skb); | 4264 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
| 4242 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) | 4265 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) |
| @@ -4404,7 +4427,7 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int | |||
| 4404 | __skb_pull(skb, hdrlen); | 4427 | __skb_pull(skb, hdrlen); |
| 4405 | eaten = (tail && | 4428 | eaten = (tail && |
| 4406 | tcp_try_coalesce(sk, tail, skb, fragstolen)) ? 1 : 0; | 4429 | tcp_try_coalesce(sk, tail, skb, fragstolen)) ? 1 : 0; |
| 4407 | tcp_sk(sk)->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 4430 | tcp_rcv_nxt_update(tcp_sk(sk), TCP_SKB_CB(skb)->end_seq); |
| 4408 | if (!eaten) { | 4431 | if (!eaten) { |
| 4409 | __skb_queue_tail(&sk->sk_receive_queue, skb); | 4432 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
| 4410 | skb_set_owner_r(skb, sk); | 4433 | skb_set_owner_r(skb, sk); |
| @@ -4497,7 +4520,7 @@ queue_and_out: | |||
| 4497 | 4520 | ||
| 4498 | eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen); | 4521 | eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen); |
| 4499 | } | 4522 | } |
| 4500 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 4523 | tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq); |
| 4501 | if (skb->len) | 4524 | if (skb->len) |
| 4502 | tcp_event_data_recv(sk, skb); | 4525 | tcp_event_data_recv(sk, skb); |
| 4503 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) | 4526 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) |
| @@ -5245,7 +5268,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
| 5245 | tcp_rcv_rtt_measure_ts(sk, skb); | 5268 | tcp_rcv_rtt_measure_ts(sk, skb); |
| 5246 | 5269 | ||
| 5247 | __skb_pull(skb, tcp_header_len); | 5270 | __skb_pull(skb, tcp_header_len); |
| 5248 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 5271 | tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq); |
| 5249 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITSTOUSER); | 5272 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITSTOUSER); |
| 5250 | eaten = 1; | 5273 | eaten = 1; |
| 5251 | } | 5274 | } |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3571f2be4470..fc1c658ec6c1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -1348,7 +1348,8 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
| 1348 | req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr); | 1348 | req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr); |
| 1349 | if (req) { | 1349 | if (req) { |
| 1350 | nsk = tcp_check_req(sk, skb, req, false); | 1350 | nsk = tcp_check_req(sk, skb, req, false); |
| 1351 | reqsk_put(req); | 1351 | if (!nsk) |
| 1352 | reqsk_put(req); | ||
| 1352 | return nsk; | 1353 | return nsk; |
| 1353 | } | 1354 | } |
| 1354 | 1355 | ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 63d6311b5365..17e7339ee5ca 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
| @@ -300,7 +300,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
| 300 | tw->tw_v6_daddr = sk->sk_v6_daddr; | 300 | tw->tw_v6_daddr = sk->sk_v6_daddr; |
| 301 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; | 301 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
| 302 | tw->tw_tclass = np->tclass; | 302 | tw->tw_tclass = np->tclass; |
| 303 | tw->tw_flowlabel = np->flow_label >> 12; | 303 | tw->tw_flowlabel = be32_to_cpu(np->flow_label & IPV6_FLOWLABEL_MASK); |
| 304 | tw->tw_ipv6only = sk->sk_ipv6only; | 304 | tw->tw_ipv6only = sk->sk_ipv6only; |
| 305 | } | 305 | } |
| 306 | #endif | 306 | #endif |
| @@ -420,7 +420,10 @@ void tcp_ca_openreq_child(struct sock *sk, const struct dst_entry *dst) | |||
| 420 | rcu_read_unlock(); | 420 | rcu_read_unlock(); |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | if (!ca_got_dst && !try_module_get(icsk->icsk_ca_ops->owner)) | 423 | /* If no valid choice made yet, assign current system default ca. */ |
| 424 | if (!ca_got_dst && | ||
| 425 | (!icsk->icsk_ca_setsockopt || | ||
| 426 | !try_module_get(icsk->icsk_ca_ops->owner))) | ||
| 424 | tcp_assign_congestion_control(sk); | 427 | tcp_assign_congestion_control(sk); |
| 425 | 428 | ||
| 426 | tcp_set_ca_state(sk, TCP_CA_Open); | 429 | tcp_set_ca_state(sk, TCP_CA_Open); |
| @@ -755,10 +758,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
| 755 | if (!child) | 758 | if (!child) |
| 756 | goto listen_overflow; | 759 | goto listen_overflow; |
| 757 | 760 | ||
| 758 | inet_csk_reqsk_queue_unlink(sk, req); | 761 | inet_csk_reqsk_queue_drop(sk, req); |
| 759 | inet_csk_reqsk_queue_removed(sk, req); | ||
| 760 | |||
| 761 | inet_csk_reqsk_queue_add(sk, req, child); | 762 | inet_csk_reqsk_queue_add(sk, req, child); |
| 763 | /* Warning: caller must not call reqsk_put(req); | ||
| 764 | * child stole last reference on it. | ||
| 765 | */ | ||
| 762 | return child; | 766 | return child; |
| 763 | 767 | ||
| 764 | listen_overflow: | 768 | listen_overflow: |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8c8d7e06b72f..a369e8a70b2c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -2812,39 +2812,65 @@ begin_fwd: | |||
| 2812 | } | 2812 | } |
| 2813 | } | 2813 | } |
| 2814 | 2814 | ||
| 2815 | /* Send a fin. The caller locks the socket for us. This cannot be | 2815 | /* We allow to exceed memory limits for FIN packets to expedite |
| 2816 | * allowed to fail queueing a FIN frame under any circumstances. | 2816 | * connection tear down and (memory) recovery. |
| 2817 | * Otherwise tcp_send_fin() could be tempted to either delay FIN | ||
| 2818 | * or even be forced to close flow without any FIN. | ||
| 2819 | */ | ||
| 2820 | static void sk_forced_wmem_schedule(struct sock *sk, int size) | ||
| 2821 | { | ||
| 2822 | int amt, status; | ||
| 2823 | |||
| 2824 | if (size <= sk->sk_forward_alloc) | ||
| 2825 | return; | ||
| 2826 | amt = sk_mem_pages(size); | ||
| 2827 | sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; | ||
| 2828 | sk_memory_allocated_add(sk, amt, &status); | ||
| 2829 | } | ||
| 2830 | |||
| 2831 | /* Send a FIN. The caller locks the socket for us. | ||
| 2832 | * We should try to send a FIN packet really hard, but eventually give up. | ||
| 2817 | */ | 2833 | */ |
| 2818 | void tcp_send_fin(struct sock *sk) | 2834 | void tcp_send_fin(struct sock *sk) |
| 2819 | { | 2835 | { |
| 2836 | struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk); | ||
| 2820 | struct tcp_sock *tp = tcp_sk(sk); | 2837 | struct tcp_sock *tp = tcp_sk(sk); |
| 2821 | struct sk_buff *skb = tcp_write_queue_tail(sk); | ||
| 2822 | int mss_now; | ||
| 2823 | 2838 | ||
| 2824 | /* Optimization, tack on the FIN if we have a queue of | 2839 | /* Optimization, tack on the FIN if we have one skb in write queue and |
| 2825 | * unsent frames. But be careful about outgoing SACKS | 2840 | * this skb was not yet sent, or we are under memory pressure. |
| 2826 | * and IP options. | 2841 | * Note: in the latter case, FIN packet will be sent after a timeout, |
| 2842 | * as TCP stack thinks it has already been transmitted. | ||
| 2827 | */ | 2843 | */ |
| 2828 | mss_now = tcp_current_mss(sk); | 2844 | if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) { |
| 2829 | 2845 | coalesce: | |
| 2830 | if (tcp_send_head(sk)) { | 2846 | TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN; |
| 2831 | TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN; | 2847 | TCP_SKB_CB(tskb)->end_seq++; |
| 2832 | TCP_SKB_CB(skb)->end_seq++; | ||
| 2833 | tp->write_seq++; | 2848 | tp->write_seq++; |
| 2849 | if (!tcp_send_head(sk)) { | ||
| 2850 | /* This means tskb was already sent. | ||
| 2851 | * Pretend we included the FIN on previous transmit. | ||
| 2852 | * We need to set tp->snd_nxt to the value it would have | ||
| 2853 | * if FIN had been sent. This is because retransmit path | ||
| 2854 | * does not change tp->snd_nxt. | ||
| 2855 | */ | ||
| 2856 | tp->snd_nxt++; | ||
| 2857 | return; | ||
| 2858 | } | ||
| 2834 | } else { | 2859 | } else { |
| 2835 | /* Socket is locked, keep trying until memory is available. */ | 2860 | skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation); |
| 2836 | for (;;) { | 2861 | if (unlikely(!skb)) { |
| 2837 | skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); | 2862 | if (tskb) |
| 2838 | if (skb) | 2863 | goto coalesce; |
| 2839 | break; | 2864 | return; |
| 2840 | yield(); | ||
| 2841 | } | 2865 | } |
| 2866 | skb_reserve(skb, MAX_TCP_HEADER); | ||
| 2867 | sk_forced_wmem_schedule(sk, skb->truesize); | ||
| 2842 | /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ | 2868 | /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ |
| 2843 | tcp_init_nondata_skb(skb, tp->write_seq, | 2869 | tcp_init_nondata_skb(skb, tp->write_seq, |
| 2844 | TCPHDR_ACK | TCPHDR_FIN); | 2870 | TCPHDR_ACK | TCPHDR_FIN); |
| 2845 | tcp_queue_skb(sk, skb); | 2871 | tcp_queue_skb(sk, skb); |
| 2846 | } | 2872 | } |
| 2847 | __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF); | 2873 | __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF); |
| 2848 | } | 2874 | } |
| 2849 | 2875 | ||
| 2850 | /* We get here when a process closes a file descriptor (either due to | 2876 | /* We get here when a process closes a file descriptor (either due to |
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index c71a1b8f7bde..a6cea1d5e20d 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c | |||
| @@ -286,18 +286,19 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | /* Extract info for Tcp socket info provided via netlink. */ | 288 | /* Extract info for Tcp socket info provided via netlink. */ |
| 289 | int tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb) | 289 | size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr, |
| 290 | union tcp_cc_info *info) | ||
| 290 | { | 291 | { |
| 291 | const struct vegas *ca = inet_csk_ca(sk); | 292 | const struct vegas *ca = inet_csk_ca(sk); |
| 293 | |||
| 292 | if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) { | 294 | if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) { |
| 293 | struct tcpvegas_info info = { | 295 | info->vegas.tcpv_enabled = ca->doing_vegas_now, |
| 294 | .tcpv_enabled = ca->doing_vegas_now, | 296 | info->vegas.tcpv_rttcnt = ca->cntRTT, |
| 295 | .tcpv_rttcnt = ca->cntRTT, | 297 | info->vegas.tcpv_rtt = ca->baseRTT, |
| 296 | .tcpv_rtt = ca->baseRTT, | 298 | info->vegas.tcpv_minrtt = ca->minRTT, |
| 297 | .tcpv_minrtt = ca->minRTT, | 299 | |
| 298 | }; | 300 | *attr = INET_DIAG_VEGASINFO; |
| 299 | 301 | return sizeof(struct tcpvegas_info); | |
| 300 | return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); | ||
| 301 | } | 302 | } |
| 302 | return 0; | 303 | return 0; |
| 303 | } | 304 | } |
diff --git a/net/ipv4/tcp_vegas.h b/net/ipv4/tcp_vegas.h index e8a6b33cc61d..ef9da5306c68 100644 --- a/net/ipv4/tcp_vegas.h +++ b/net/ipv4/tcp_vegas.h | |||
| @@ -19,6 +19,7 @@ void tcp_vegas_init(struct sock *sk); | |||
| 19 | void tcp_vegas_state(struct sock *sk, u8 ca_state); | 19 | void tcp_vegas_state(struct sock *sk, u8 ca_state); |
| 20 | void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us); | 20 | void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us); |
| 21 | void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event); | 21 | void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event); |
| 22 | int tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb); | 22 | size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr, |
| 23 | union tcp_cc_info *info); | ||
| 23 | 24 | ||
| 24 | #endif /* __TCP_VEGAS_H */ | 25 | #endif /* __TCP_VEGAS_H */ |
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c index b3c57cceb990..c10732e39837 100644 --- a/net/ipv4/tcp_westwood.c +++ b/net/ipv4/tcp_westwood.c | |||
| @@ -256,18 +256,19 @@ static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event) | |||
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | /* Extract info for Tcp socket info provided via netlink. */ | 258 | /* Extract info for Tcp socket info provided via netlink. */ |
| 259 | static int tcp_westwood_info(struct sock *sk, u32 ext, struct sk_buff *skb) | 259 | static size_t tcp_westwood_info(struct sock *sk, u32 ext, int *attr, |
| 260 | union tcp_cc_info *info) | ||
| 260 | { | 261 | { |
| 261 | const struct westwood *ca = inet_csk_ca(sk); | 262 | const struct westwood *ca = inet_csk_ca(sk); |
| 262 | 263 | ||
| 263 | if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) { | 264 | if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) { |
| 264 | struct tcpvegas_info info = { | 265 | info->vegas.tcpv_enabled = 1; |
| 265 | .tcpv_enabled = 1, | 266 | info->vegas.tcpv_rttcnt = 0; |
| 266 | .tcpv_rtt = jiffies_to_usecs(ca->rtt), | 267 | info->vegas.tcpv_rtt = jiffies_to_usecs(ca->rtt), |
| 267 | .tcpv_minrtt = jiffies_to_usecs(ca->rtt_min), | 268 | info->vegas.tcpv_minrtt = jiffies_to_usecs(ca->rtt_min), |
| 268 | }; | ||
| 269 | 269 | ||
| 270 | return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); | 270 | *attr = INET_DIAG_VEGASINFO; |
| 271 | return sizeof(struct tcpvegas_info); | ||
| 271 | } | 272 | } |
| 272 | return 0; | 273 | return 0; |
| 273 | } | 274 | } |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d10b7e0112eb..83aa604f9273 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -90,6 +90,7 @@ | |||
| 90 | #include <linux/socket.h> | 90 | #include <linux/socket.h> |
| 91 | #include <linux/sockios.h> | 91 | #include <linux/sockios.h> |
| 92 | #include <linux/igmp.h> | 92 | #include <linux/igmp.h> |
| 93 | #include <linux/inetdevice.h> | ||
| 93 | #include <linux/in.h> | 94 | #include <linux/in.h> |
| 94 | #include <linux/errno.h> | 95 | #include <linux/errno.h> |
| 95 | #include <linux/timer.h> | 96 | #include <linux/timer.h> |
| @@ -1345,10 +1346,8 @@ csum_copy_err: | |||
| 1345 | } | 1346 | } |
| 1346 | unlock_sock_fast(sk, slow); | 1347 | unlock_sock_fast(sk, slow); |
| 1347 | 1348 | ||
| 1348 | if (noblock) | 1349 | /* starting over for a new packet, but check if we need to yield */ |
| 1349 | return -EAGAIN; | 1350 | cond_resched(); |
| 1350 | |||
| 1351 | /* starting over for a new packet */ | ||
| 1352 | msg->msg_flags &= ~MSG_TRUNC; | 1351 | msg->msg_flags &= ~MSG_TRUNC; |
| 1353 | goto try_again; | 1352 | goto try_again; |
| 1354 | } | 1353 | } |
| @@ -1962,6 +1961,7 @@ void udp_v4_early_demux(struct sk_buff *skb) | |||
| 1962 | struct sock *sk; | 1961 | struct sock *sk; |
| 1963 | struct dst_entry *dst; | 1962 | struct dst_entry *dst; |
| 1964 | int dif = skb->dev->ifindex; | 1963 | int dif = skb->dev->ifindex; |
| 1964 | int ours; | ||
| 1965 | 1965 | ||
| 1966 | /* validate the packet */ | 1966 | /* validate the packet */ |
| 1967 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) | 1967 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) |
| @@ -1971,14 +1971,24 @@ void udp_v4_early_demux(struct sk_buff *skb) | |||
| 1971 | uh = udp_hdr(skb); | 1971 | uh = udp_hdr(skb); |
| 1972 | 1972 | ||
| 1973 | if (skb->pkt_type == PACKET_BROADCAST || | 1973 | if (skb->pkt_type == PACKET_BROADCAST || |
| 1974 | skb->pkt_type == PACKET_MULTICAST) | 1974 | skb->pkt_type == PACKET_MULTICAST) { |
| 1975 | struct in_device *in_dev = __in_dev_get_rcu(skb->dev); | ||
| 1976 | |||
| 1977 | if (!in_dev) | ||
| 1978 | return; | ||
| 1979 | |||
| 1980 | ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, | ||
| 1981 | iph->protocol); | ||
| 1982 | if (!ours) | ||
| 1983 | return; | ||
| 1975 | sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, | 1984 | sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, |
| 1976 | uh->source, iph->saddr, dif); | 1985 | uh->source, iph->saddr, dif); |
| 1977 | else if (skb->pkt_type == PACKET_HOST) | 1986 | } else if (skb->pkt_type == PACKET_HOST) { |
| 1978 | sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, | 1987 | sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, |
| 1979 | uh->source, iph->saddr, dif); | 1988 | uh->source, iph->saddr, dif); |
| 1980 | else | 1989 | } else { |
| 1981 | return; | 1990 | return; |
| 1991 | } | ||
| 1982 | 1992 | ||
| 1983 | if (!sk) | 1993 | if (!sk) |
| 1984 | return; | 1994 | return; |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index d873ceea86e6..ca09bf49ac68 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
| @@ -133,6 +133,14 @@ static void snmp6_free_dev(struct inet6_dev *idev) | |||
| 133 | free_percpu(idev->stats.ipv6); | 133 | free_percpu(idev->stats.ipv6); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) | ||
| 137 | { | ||
| 138 | struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu); | ||
| 139 | |||
| 140 | snmp6_free_dev(idev); | ||
| 141 | kfree(idev); | ||
| 142 | } | ||
| 143 | |||
| 136 | /* Nobody refers to this device, we may destroy it. */ | 144 | /* Nobody refers to this device, we may destroy it. */ |
| 137 | 145 | ||
| 138 | void in6_dev_finish_destroy(struct inet6_dev *idev) | 146 | void in6_dev_finish_destroy(struct inet6_dev *idev) |
| @@ -151,7 +159,6 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
| 151 | pr_warn("Freeing alive inet6 device %p\n", idev); | 159 | pr_warn("Freeing alive inet6 device %p\n", idev); |
| 152 | return; | 160 | return; |
| 153 | } | 161 | } |
| 154 | snmp6_free_dev(idev); | 162 | call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); |
| 155 | kfree_rcu(idev, rcu); | ||
| 156 | } | 163 | } |
| 157 | EXPORT_SYMBOL(in6_dev_finish_destroy); | 164 | EXPORT_SYMBOL(in6_dev_finish_destroy); |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 31f1b5d5e2ef..7c07ce36aae2 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
| @@ -248,7 +248,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 248 | aead_givcrypt_set_crypt(req, sg, sg, clen, iv); | 248 | aead_givcrypt_set_crypt(req, sg, sg, clen, iv); |
| 249 | aead_givcrypt_set_assoc(req, asg, assoclen); | 249 | aead_givcrypt_set_assoc(req, asg, assoclen); |
| 250 | aead_givcrypt_set_giv(req, esph->enc_data, | 250 | aead_givcrypt_set_giv(req, esph->enc_data, |
| 251 | XFRM_SKB_CB(skb)->seq.output.low); | 251 | XFRM_SKB_CB(skb)->seq.output.low + |
| 252 | ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32)); | ||
| 252 | 253 | ||
| 253 | ESP_SKB_CB(skb)->tmp = tmp; | 254 | ESP_SKB_CB(skb)->tmp = tmp; |
| 254 | err = crypto_aead_givencrypt(req); | 255 | err = crypto_aead_givencrypt(req); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 96dbffff5a24..bde57b113009 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -693,6 +693,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 693 | { | 693 | { |
| 694 | struct rt6_info *iter = NULL; | 694 | struct rt6_info *iter = NULL; |
| 695 | struct rt6_info **ins; | 695 | struct rt6_info **ins; |
| 696 | struct rt6_info **fallback_ins = NULL; | ||
| 696 | int replace = (info->nlh && | 697 | int replace = (info->nlh && |
| 697 | (info->nlh->nlmsg_flags & NLM_F_REPLACE)); | 698 | (info->nlh->nlmsg_flags & NLM_F_REPLACE)); |
| 698 | int add = (!info->nlh || | 699 | int add = (!info->nlh || |
| @@ -716,8 +717,13 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 716 | (info->nlh->nlmsg_flags & NLM_F_EXCL)) | 717 | (info->nlh->nlmsg_flags & NLM_F_EXCL)) |
| 717 | return -EEXIST; | 718 | return -EEXIST; |
| 718 | if (replace) { | 719 | if (replace) { |
| 719 | found++; | 720 | if (rt_can_ecmp == rt6_qualify_for_ecmp(iter)) { |
| 720 | break; | 721 | found++; |
| 722 | break; | ||
| 723 | } | ||
| 724 | if (rt_can_ecmp) | ||
| 725 | fallback_ins = fallback_ins ?: ins; | ||
| 726 | goto next_iter; | ||
| 721 | } | 727 | } |
| 722 | 728 | ||
| 723 | if (iter->dst.dev == rt->dst.dev && | 729 | if (iter->dst.dev == rt->dst.dev && |
| @@ -753,9 +759,17 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 753 | if (iter->rt6i_metric > rt->rt6i_metric) | 759 | if (iter->rt6i_metric > rt->rt6i_metric) |
| 754 | break; | 760 | break; |
| 755 | 761 | ||
| 762 | next_iter: | ||
| 756 | ins = &iter->dst.rt6_next; | 763 | ins = &iter->dst.rt6_next; |
| 757 | } | 764 | } |
| 758 | 765 | ||
| 766 | if (fallback_ins && !found) { | ||
| 767 | /* No ECMP-able route found, replace first non-ECMP one */ | ||
| 768 | ins = fallback_ins; | ||
| 769 | iter = *ins; | ||
| 770 | found++; | ||
| 771 | } | ||
| 772 | |||
| 759 | /* Reset round-robin state, if necessary */ | 773 | /* Reset round-robin state, if necessary */ |
| 760 | if (ins == &fn->leaf) | 774 | if (ins == &fn->leaf) |
| 761 | fn->rr_ptr = NULL; | 775 | fn->rr_ptr = NULL; |
| @@ -815,6 +829,8 @@ add: | |||
| 815 | } | 829 | } |
| 816 | 830 | ||
| 817 | } else { | 831 | } else { |
| 832 | int nsiblings; | ||
| 833 | |||
| 818 | if (!found) { | 834 | if (!found) { |
| 819 | if (add) | 835 | if (add) |
| 820 | goto add; | 836 | goto add; |
| @@ -835,8 +851,27 @@ add: | |||
| 835 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | 851 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
| 836 | fn->fn_flags |= RTN_RTINFO; | 852 | fn->fn_flags |= RTN_RTINFO; |
| 837 | } | 853 | } |
| 854 | nsiblings = iter->rt6i_nsiblings; | ||
| 838 | fib6_purge_rt(iter, fn, info->nl_net); | 855 | fib6_purge_rt(iter, fn, info->nl_net); |
| 839 | rt6_release(iter); | 856 | rt6_release(iter); |
| 857 | |||
| 858 | if (nsiblings) { | ||
| 859 | /* Replacing an ECMP route, remove all siblings */ | ||
| 860 | ins = &rt->dst.rt6_next; | ||
| 861 | iter = *ins; | ||
| 862 | while (iter) { | ||
| 863 | if (rt6_qualify_for_ecmp(iter)) { | ||
| 864 | *ins = iter->dst.rt6_next; | ||
| 865 | fib6_purge_rt(iter, fn, info->nl_net); | ||
| 866 | rt6_release(iter); | ||
| 867 | nsiblings--; | ||
| 868 | } else { | ||
| 869 | ins = &iter->dst.rt6_next; | ||
| 870 | } | ||
| 871 | iter = *ins; | ||
| 872 | } | ||
| 873 | WARN_ON(nsiblings != 0); | ||
| 874 | } | ||
| 840 | } | 875 | } |
| 841 | 876 | ||
| 842 | return 0; | 877 | return 0; |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index b5e6cc1d4a73..a38d3ac0f18f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -1246,7 +1246,6 @@ static void ip6gre_tunnel_setup(struct net_device *dev) | |||
| 1246 | static int ip6gre_tunnel_init(struct net_device *dev) | 1246 | static int ip6gre_tunnel_init(struct net_device *dev) |
| 1247 | { | 1247 | { |
| 1248 | struct ip6_tnl *tunnel; | 1248 | struct ip6_tnl *tunnel; |
| 1249 | int i; | ||
| 1250 | 1249 | ||
| 1251 | tunnel = netdev_priv(dev); | 1250 | tunnel = netdev_priv(dev); |
| 1252 | 1251 | ||
| @@ -1260,16 +1259,10 @@ static int ip6gre_tunnel_init(struct net_device *dev) | |||
| 1260 | if (ipv6_addr_any(&tunnel->parms.raddr)) | 1259 | if (ipv6_addr_any(&tunnel->parms.raddr)) |
| 1261 | dev->header_ops = &ip6gre_header_ops; | 1260 | dev->header_ops = &ip6gre_header_ops; |
| 1262 | 1261 | ||
| 1263 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1262 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 1264 | if (!dev->tstats) | 1263 | if (!dev->tstats) |
| 1265 | return -ENOMEM; | 1264 | return -ENOMEM; |
| 1266 | 1265 | ||
| 1267 | for_each_possible_cpu(i) { | ||
| 1268 | struct pcpu_sw_netstats *ip6gre_tunnel_stats; | ||
| 1269 | ip6gre_tunnel_stats = per_cpu_ptr(dev->tstats, i); | ||
| 1270 | u64_stats_init(&ip6gre_tunnel_stats->syncp); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | return 0; | 1266 | return 0; |
| 1274 | } | 1267 | } |
| 1275 | 1268 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7fde1f265c90..bc09cb97b840 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -886,22 +886,45 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
| 886 | #endif | 886 | #endif |
| 887 | int err; | 887 | int err; |
| 888 | 888 | ||
| 889 | if (!*dst) | 889 | /* The correct way to handle this would be to do |
| 890 | *dst = ip6_route_output(net, sk, fl6); | 890 | * ip6_route_get_saddr, and then ip6_route_output; however, |
| 891 | 891 | * the route-specific preferred source forces the | |
| 892 | err = (*dst)->error; | 892 | * ip6_route_output call _before_ ip6_route_get_saddr. |
| 893 | if (err) | 893 | * |
| 894 | goto out_err_release; | 894 | * In source specific routing (no src=any default route), |
| 895 | * ip6_route_output will fail given src=any saddr, though, so | ||
| 896 | * that's why we try it again later. | ||
| 897 | */ | ||
| 898 | if (ipv6_addr_any(&fl6->saddr) && (!*dst || !(*dst)->error)) { | ||
| 899 | struct rt6_info *rt; | ||
| 900 | bool had_dst = *dst != NULL; | ||
| 895 | 901 | ||
| 896 | if (ipv6_addr_any(&fl6->saddr)) { | 902 | if (!had_dst) |
| 897 | struct rt6_info *rt = (struct rt6_info *) *dst; | 903 | *dst = ip6_route_output(net, sk, fl6); |
| 904 | rt = (*dst)->error ? NULL : (struct rt6_info *)*dst; | ||
| 898 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, | 905 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, |
| 899 | sk ? inet6_sk(sk)->srcprefs : 0, | 906 | sk ? inet6_sk(sk)->srcprefs : 0, |
| 900 | &fl6->saddr); | 907 | &fl6->saddr); |
| 901 | if (err) | 908 | if (err) |
| 902 | goto out_err_release; | 909 | goto out_err_release; |
| 910 | |||
| 911 | /* If we had an erroneous initial result, pretend it | ||
| 912 | * never existed and let the SA-enabled version take | ||
| 913 | * over. | ||
| 914 | */ | ||
| 915 | if (!had_dst && (*dst)->error) { | ||
| 916 | dst_release(*dst); | ||
| 917 | *dst = NULL; | ||
| 918 | } | ||
| 903 | } | 919 | } |
| 904 | 920 | ||
| 921 | if (!*dst) | ||
| 922 | *dst = ip6_route_output(net, sk, fl6); | ||
| 923 | |||
| 924 | err = (*dst)->error; | ||
| 925 | if (err) | ||
| 926 | goto out_err_release; | ||
| 927 | |||
| 905 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 928 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
| 906 | /* | 929 | /* |
| 907 | * Here if the dst entry we've looked up | 930 | * Here if the dst entry we've looked up |
| @@ -1277,8 +1300,10 @@ emsgsize: | |||
| 1277 | 1300 | ||
| 1278 | /* If this is the first and only packet and device | 1301 | /* If this is the first and only packet and device |
| 1279 | * supports checksum offloading, let's use it. | 1302 | * supports checksum offloading, let's use it. |
| 1303 | * Use transhdrlen, same as IPv4, because partial | ||
| 1304 | * sums only work when transhdrlen is set. | ||
| 1280 | */ | 1305 | */ |
| 1281 | if (!skb && sk->sk_protocol == IPPROTO_UDP && | 1306 | if (transhdrlen && sk->sk_protocol == IPPROTO_UDP && |
| 1282 | length + fragheaderlen < mtu && | 1307 | length + fragheaderlen < mtu && |
| 1283 | rt->dst.dev->features & NETIF_F_V6_CSUM && | 1308 | rt->dst.dev->features & NETIF_F_V6_CSUM && |
| 1284 | !exthdrlen) | 1309 | !exthdrlen) |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index ed9d681207fa..0224c032dca5 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
| @@ -322,7 +322,6 @@ static int vti6_rcv(struct sk_buff *skb) | |||
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t; | 324 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t; |
| 325 | skb->mark = be32_to_cpu(t->parms.i_key); | ||
| 326 | 325 | ||
| 327 | rcu_read_unlock(); | 326 | rcu_read_unlock(); |
| 328 | 327 | ||
| @@ -342,6 +341,8 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err) | |||
| 342 | struct pcpu_sw_netstats *tstats; | 341 | struct pcpu_sw_netstats *tstats; |
| 343 | struct xfrm_state *x; | 342 | struct xfrm_state *x; |
| 344 | struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; | 343 | struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; |
| 344 | u32 orig_mark = skb->mark; | ||
| 345 | int ret; | ||
| 345 | 346 | ||
| 346 | if (!t) | 347 | if (!t) |
| 347 | return 1; | 348 | return 1; |
| @@ -358,7 +359,11 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err) | |||
| 358 | x = xfrm_input_state(skb); | 359 | x = xfrm_input_state(skb); |
| 359 | family = x->inner_mode->afinfo->family; | 360 | family = x->inner_mode->afinfo->family; |
| 360 | 361 | ||
| 361 | if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) | 362 | skb->mark = be32_to_cpu(t->parms.i_key); |
| 363 | ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); | ||
| 364 | skb->mark = orig_mark; | ||
| 365 | |||
| 366 | if (!ret) | ||
| 362 | return -EPERM; | 367 | return -EPERM; |
| 363 | 368 | ||
| 364 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev))); | 369 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev))); |
| @@ -430,6 +435,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) | |||
| 430 | struct net_device *tdev; | 435 | struct net_device *tdev; |
| 431 | struct xfrm_state *x; | 436 | struct xfrm_state *x; |
| 432 | int err = -1; | 437 | int err = -1; |
| 438 | int mtu; | ||
| 433 | 439 | ||
| 434 | if (!dst) | 440 | if (!dst) |
| 435 | goto tx_err_link_failure; | 441 | goto tx_err_link_failure; |
| @@ -463,6 +469,19 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) | |||
| 463 | skb_dst_set(skb, dst); | 469 | skb_dst_set(skb, dst); |
| 464 | skb->dev = skb_dst(skb)->dev; | 470 | skb->dev = skb_dst(skb)->dev; |
| 465 | 471 | ||
| 472 | mtu = dst_mtu(dst); | ||
| 473 | if (!skb->ignore_df && skb->len > mtu) { | ||
| 474 | skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu); | ||
| 475 | |||
| 476 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
| 477 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | ||
| 478 | else | ||
| 479 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | ||
| 480 | htonl(mtu)); | ||
| 481 | |||
| 482 | return -EMSGSIZE; | ||
| 483 | } | ||
| 484 | |||
| 466 | err = dst_output(skb); | 485 | err = dst_output(skb); |
| 467 | if (net_xmit_eval(err) == 0) { | 486 | if (net_xmit_eval(err) == 0) { |
| 468 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); | 487 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); |
| @@ -495,7 +514,6 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 495 | int ret; | 514 | int ret; |
| 496 | 515 | ||
| 497 | memset(&fl, 0, sizeof(fl)); | 516 | memset(&fl, 0, sizeof(fl)); |
| 498 | skb->mark = be32_to_cpu(t->parms.o_key); | ||
| 499 | 517 | ||
| 500 | switch (skb->protocol) { | 518 | switch (skb->protocol) { |
| 501 | case htons(ETH_P_IPV6): | 519 | case htons(ETH_P_IPV6): |
| @@ -516,6 +534,9 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 516 | goto tx_err; | 534 | goto tx_err; |
| 517 | } | 535 | } |
| 518 | 536 | ||
| 537 | /* override mark with tunnel output key */ | ||
| 538 | fl.flowi_mark = be32_to_cpu(t->parms.o_key); | ||
| 539 | |||
| 519 | ret = vti6_xmit(skb, dev, &fl); | 540 | ret = vti6_xmit(skb, dev, &fl); |
| 520 | if (ret < 0) | 541 | if (ret < 0) |
| 521 | goto tx_err; | 542 | goto tx_err; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1a732a1d3c8e..62f5b0d0bc9b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -1275,6 +1275,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
| 1275 | /* overflow check */ | 1275 | /* overflow check */ |
| 1276 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1276 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
| 1277 | return -ENOMEM; | 1277 | return -ENOMEM; |
| 1278 | if (tmp.num_counters == 0) | ||
| 1279 | return -EINVAL; | ||
| 1280 | |||
| 1278 | tmp.name[sizeof(tmp.name)-1] = 0; | 1281 | tmp.name[sizeof(tmp.name)-1] = 0; |
| 1279 | 1282 | ||
| 1280 | newinfo = xt_alloc_table_info(tmp.size); | 1283 | newinfo = xt_alloc_table_info(tmp.size); |
| @@ -1822,6 +1825,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
| 1822 | return -ENOMEM; | 1825 | return -ENOMEM; |
| 1823 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1826 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
| 1824 | return -ENOMEM; | 1827 | return -ENOMEM; |
| 1828 | if (tmp.num_counters == 0) | ||
| 1829 | return -EINVAL; | ||
| 1830 | |||
| 1825 | tmp.name[sizeof(tmp.name)-1] = 0; | 1831 | tmp.name[sizeof(tmp.name)-1] = 0; |
| 1826 | 1832 | ||
| 1827 | newinfo = xt_alloc_table_info(tmp.size); | 1833 | newinfo = xt_alloc_table_info(tmp.size); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5c48293ff062..c73ae5039e46 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -2245,9 +2245,10 @@ int ip6_route_get_saddr(struct net *net, | |||
| 2245 | unsigned int prefs, | 2245 | unsigned int prefs, |
| 2246 | struct in6_addr *saddr) | 2246 | struct in6_addr *saddr) |
| 2247 | { | 2247 | { |
| 2248 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt); | 2248 | struct inet6_dev *idev = |
| 2249 | rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL; | ||
| 2249 | int err = 0; | 2250 | int err = 0; |
| 2250 | if (rt->rt6i_prefsrc.plen) | 2251 | if (rt && rt->rt6i_prefsrc.plen) |
| 2251 | *saddr = rt->rt6i_prefsrc.addr; | 2252 | *saddr = rt->rt6i_prefsrc.addr; |
| 2252 | else | 2253 | else |
| 2253 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2254 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
| @@ -2503,9 +2504,9 @@ static int ip6_route_multipath(struct fib6_config *cfg, int add) | |||
| 2503 | int attrlen; | 2504 | int attrlen; |
| 2504 | int err = 0, last_err = 0; | 2505 | int err = 0, last_err = 0; |
| 2505 | 2506 | ||
| 2507 | remaining = cfg->fc_mp_len; | ||
| 2506 | beginning: | 2508 | beginning: |
| 2507 | rtnh = (struct rtnexthop *)cfg->fc_mp; | 2509 | rtnh = (struct rtnexthop *)cfg->fc_mp; |
| 2508 | remaining = cfg->fc_mp_len; | ||
| 2509 | 2510 | ||
| 2510 | /* Parse a Multipath Entry */ | 2511 | /* Parse a Multipath Entry */ |
| 2511 | while (rtnh_ok(rtnh, remaining)) { | 2512 | while (rtnh_ok(rtnh, remaining)) { |
| @@ -2535,15 +2536,19 @@ beginning: | |||
| 2535 | * next hops that have been already added. | 2536 | * next hops that have been already added. |
| 2536 | */ | 2537 | */ |
| 2537 | add = 0; | 2538 | add = 0; |
| 2539 | remaining = cfg->fc_mp_len - remaining; | ||
| 2538 | goto beginning; | 2540 | goto beginning; |
| 2539 | } | 2541 | } |
| 2540 | } | 2542 | } |
| 2541 | /* Because each route is added like a single route we remove | 2543 | /* Because each route is added like a single route we remove |
| 2542 | * this flag after the first nexthop (if there is a collision, | 2544 | * these flags after the first nexthop: if there is a collision, |
| 2543 | * we have already fail to add the first nexthop: | 2545 | * we have already failed to add the first nexthop: |
| 2544 | * fib6_add_rt2node() has reject it). | 2546 | * fib6_add_rt2node() has rejected it; when replacing, old |
| 2547 | * nexthops have been replaced by first new, the rest should | ||
| 2548 | * be added to it. | ||
| 2545 | */ | 2549 | */ |
| 2546 | cfg->fc_nlinfo.nlh->nlmsg_flags &= ~NLM_F_EXCL; | 2550 | cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | |
| 2551 | NLM_F_REPLACE); | ||
| 2547 | rtnh = rtnh_next(rtnh, &remaining); | 2552 | rtnh = rtnh_next(rtnh, &remaining); |
| 2548 | } | 2553 | } |
| 2549 | 2554 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index ad51df85aa00..3adffb300238 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -914,7 +914,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
| 914 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 914 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
| 915 | tcp_time_stamp + tcptw->tw_ts_offset, | 915 | tcp_time_stamp + tcptw->tw_ts_offset, |
| 916 | tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), | 916 | tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), |
| 917 | tw->tw_tclass, (tw->tw_flowlabel << 12)); | 917 | tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel)); |
| 918 | 918 | ||
| 919 | inet_twsk_put(tw); | 919 | inet_twsk_put(tw); |
| 920 | } | 920 | } |
| @@ -946,7 +946,8 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
| 946 | &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); | 946 | &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); |
| 947 | if (req) { | 947 | if (req) { |
| 948 | nsk = tcp_check_req(sk, skb, req, false); | 948 | nsk = tcp_check_req(sk, skb, req, false); |
| 949 | reqsk_put(req); | 949 | if (!nsk) |
| 950 | reqsk_put(req); | ||
| 950 | return nsk; | 951 | return nsk; |
| 951 | } | 952 | } |
| 952 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, | 953 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 3477c919fcc8..e51fc3eee6db 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -525,10 +525,8 @@ csum_copy_err: | |||
| 525 | } | 525 | } |
| 526 | unlock_sock_fast(sk, slow); | 526 | unlock_sock_fast(sk, slow); |
| 527 | 527 | ||
| 528 | if (noblock) | 528 | /* starting over for a new packet, but check if we need to yield */ |
| 529 | return -EAGAIN; | 529 | cond_resched(); |
| 530 | |||
| 531 | /* starting over for a new packet */ | ||
| 532 | msg->msg_flags &= ~MSG_TRUNC; | 530 | msg->msg_flags &= ~MSG_TRUNC; |
| 533 | goto try_again; | 531 | goto try_again; |
| 534 | } | 532 | } |
| @@ -731,7 +729,9 @@ static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk, | |||
| 731 | (inet->inet_dport && inet->inet_dport != rmt_port) || | 729 | (inet->inet_dport && inet->inet_dport != rmt_port) || |
| 732 | (!ipv6_addr_any(&sk->sk_v6_daddr) && | 730 | (!ipv6_addr_any(&sk->sk_v6_daddr) && |
| 733 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || | 731 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || |
| 734 | (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) | 732 | (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) || |
| 733 | (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) && | ||
| 734 | !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr))) | ||
| 735 | return false; | 735 | return false; |
| 736 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) | 736 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) |
| 737 | return false; | 737 | return false; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 265e42721a66..ff347a0eebd4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -2495,51 +2495,22 @@ static bool ieee80211_coalesce_started_roc(struct ieee80211_local *local, | |||
| 2495 | struct ieee80211_roc_work *new_roc, | 2495 | struct ieee80211_roc_work *new_roc, |
| 2496 | struct ieee80211_roc_work *cur_roc) | 2496 | struct ieee80211_roc_work *cur_roc) |
| 2497 | { | 2497 | { |
| 2498 | unsigned long j = jiffies; | 2498 | unsigned long now = jiffies; |
| 2499 | unsigned long cur_roc_end = cur_roc->hw_start_time + | 2499 | unsigned long remaining = cur_roc->hw_start_time + |
| 2500 | msecs_to_jiffies(cur_roc->duration); | 2500 | msecs_to_jiffies(cur_roc->duration) - |
| 2501 | struct ieee80211_roc_work *next_roc; | 2501 | now; |
| 2502 | int new_dur; | ||
| 2503 | 2502 | ||
| 2504 | if (WARN_ON(!cur_roc->started || !cur_roc->hw_begun)) | 2503 | if (WARN_ON(!cur_roc->started || !cur_roc->hw_begun)) |
| 2505 | return false; | 2504 | return false; |
| 2506 | 2505 | ||
| 2507 | if (time_after(j + IEEE80211_ROC_MIN_LEFT, cur_roc_end)) | 2506 | /* if it doesn't fit entirely, schedule a new one */ |
| 2507 | if (new_roc->duration > jiffies_to_msecs(remaining)) | ||
| 2508 | return false; | 2508 | return false; |
| 2509 | 2509 | ||
| 2510 | ieee80211_handle_roc_started(new_roc); | 2510 | ieee80211_handle_roc_started(new_roc); |
| 2511 | 2511 | ||
| 2512 | new_dur = new_roc->duration - jiffies_to_msecs(cur_roc_end - j); | 2512 | /* add to dependents so we send the expired event properly */ |
| 2513 | 2513 | list_add_tail(&new_roc->list, &cur_roc->dependents); | |
| 2514 | /* cur_roc is long enough - add new_roc to the dependents list. */ | ||
| 2515 | if (new_dur <= 0) { | ||
| 2516 | list_add_tail(&new_roc->list, &cur_roc->dependents); | ||
| 2517 | return true; | ||
| 2518 | } | ||
| 2519 | |||
| 2520 | new_roc->duration = new_dur; | ||
| 2521 | |||
| 2522 | /* | ||
| 2523 | * if cur_roc was already coalesced before, we might | ||
| 2524 | * want to extend the next roc instead of adding | ||
| 2525 | * a new one. | ||
| 2526 | */ | ||
| 2527 | next_roc = list_entry(cur_roc->list.next, | ||
| 2528 | struct ieee80211_roc_work, list); | ||
| 2529 | if (&next_roc->list != &local->roc_list && | ||
| 2530 | next_roc->chan == new_roc->chan && | ||
| 2531 | next_roc->sdata == new_roc->sdata && | ||
| 2532 | !WARN_ON(next_roc->started)) { | ||
| 2533 | list_add_tail(&new_roc->list, &next_roc->dependents); | ||
| 2534 | next_roc->duration = max(next_roc->duration, | ||
| 2535 | new_roc->duration); | ||
| 2536 | next_roc->type = max(next_roc->type, new_roc->type); | ||
| 2537 | return true; | ||
| 2538 | } | ||
| 2539 | |||
| 2540 | /* add right after cur_roc */ | ||
| 2541 | list_add(&new_roc->list, &cur_roc->list); | ||
| 2542 | |||
| 2543 | return true; | 2514 | return true; |
| 2544 | } | 2515 | } |
| 2545 | 2516 | ||
| @@ -2652,17 +2623,9 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
| 2652 | * In the offloaded ROC case, if it hasn't begun, add | 2623 | * In the offloaded ROC case, if it hasn't begun, add |
| 2653 | * this new one to the dependent list to be handled | 2624 | * this new one to the dependent list to be handled |
| 2654 | * when the master one begins. If it has begun, | 2625 | * when the master one begins. If it has begun, |
| 2655 | * check that there's still a minimum time left and | 2626 | * check if it fits entirely within the existing one, |
| 2656 | * if so, start this one, transmitting the frame, but | 2627 | * in which case it will just be dependent as well. |
| 2657 | * add it to the list directly after this one with | 2628 | * Otherwise, schedule it by itself. |
| 2658 | * a reduced time so we'll ask the driver to execute | ||
| 2659 | * it right after finishing the previous one, in the | ||
| 2660 | * hope that it'll also be executed right afterwards, | ||
| 2661 | * effectively extending the old one. | ||
| 2662 | * If there's no minimum time left, just add it to the | ||
| 2663 | * normal list. | ||
| 2664 | * TODO: the ROC type is ignored here, assuming that it | ||
| 2665 | * is better to immediately use the current ROC. | ||
| 2666 | */ | 2629 | */ |
| 2667 | if (!tmp->hw_begun) { | 2630 | if (!tmp->hw_begun) { |
| 2668 | list_add_tail(&roc->list, &tmp->dependents); | 2631 | list_add_tail(&roc->list, &tmp->dependents); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ab46ab4a7249..c0a9187bc3a9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -205,6 +205,8 @@ enum ieee80211_packet_rx_flags { | |||
| 205 | * @IEEE80211_RX_CMNTR: received on cooked monitor already | 205 | * @IEEE80211_RX_CMNTR: received on cooked monitor already |
| 206 | * @IEEE80211_RX_BEACON_REPORTED: This frame was already reported | 206 | * @IEEE80211_RX_BEACON_REPORTED: This frame was already reported |
| 207 | * to cfg80211_report_obss_beacon(). | 207 | * to cfg80211_report_obss_beacon(). |
| 208 | * @IEEE80211_RX_REORDER_TIMER: this frame is released by the | ||
| 209 | * reorder buffer timeout timer, not the normal RX path | ||
| 208 | * | 210 | * |
| 209 | * These flags are used across handling multiple interfaces | 211 | * These flags are used across handling multiple interfaces |
| 210 | * for a single frame. | 212 | * for a single frame. |
| @@ -212,6 +214,7 @@ enum ieee80211_packet_rx_flags { | |||
| 212 | enum ieee80211_rx_flags { | 214 | enum ieee80211_rx_flags { |
| 213 | IEEE80211_RX_CMNTR = BIT(0), | 215 | IEEE80211_RX_CMNTR = BIT(0), |
| 214 | IEEE80211_RX_BEACON_REPORTED = BIT(1), | 216 | IEEE80211_RX_BEACON_REPORTED = BIT(1), |
| 217 | IEEE80211_RX_REORDER_TIMER = BIT(2), | ||
| 215 | }; | 218 | }; |
| 216 | 219 | ||
| 217 | struct ieee80211_rx_data { | 220 | struct ieee80211_rx_data { |
| @@ -325,12 +328,6 @@ struct mesh_preq_queue { | |||
| 325 | u8 flags; | 328 | u8 flags; |
| 326 | }; | 329 | }; |
| 327 | 330 | ||
| 328 | #if HZ/100 == 0 | ||
| 329 | #define IEEE80211_ROC_MIN_LEFT 1 | ||
| 330 | #else | ||
| 331 | #define IEEE80211_ROC_MIN_LEFT (HZ/100) | ||
| 332 | #endif | ||
| 333 | |||
| 334 | struct ieee80211_roc_work { | 331 | struct ieee80211_roc_work { |
| 335 | struct list_head list; | 332 | struct list_head list; |
| 336 | struct list_head dependents; | 333 | struct list_head dependents; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b4ac596a7cb7..84cef600c573 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -522,6 +522,12 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
| 522 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, | 522 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, |
| 523 | sizeof(sdata->vif.hw_queue)); | 523 | sizeof(sdata->vif.hw_queue)); |
| 524 | sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef; | 524 | sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef; |
| 525 | |||
| 526 | mutex_lock(&local->key_mtx); | ||
| 527 | sdata->crypto_tx_tailroom_needed_cnt += | ||
| 528 | master->crypto_tx_tailroom_needed_cnt; | ||
| 529 | mutex_unlock(&local->key_mtx); | ||
| 530 | |||
| 525 | break; | 531 | break; |
| 526 | } | 532 | } |
| 527 | case NL80211_IFTYPE_AP: | 533 | case NL80211_IFTYPE_AP: |
| @@ -819,13 +825,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 819 | * (because if we remove a STA after ops->remove_interface() | 825 | * (because if we remove a STA after ops->remove_interface() |
| 820 | * the driver will have removed the vif info already!) | 826 | * the driver will have removed the vif info already!) |
| 821 | * | 827 | * |
| 822 | * This is relevant only in WDS mode, in all other modes we've | 828 | * In WDS mode a station must exist here and be flushed, for |
| 823 | * already removed all stations when disconnecting or similar, | 829 | * AP_VLANs stations may exist since there's nothing else that |
| 824 | * so warn otherwise. | 830 | * would have removed them, but in other modes there shouldn't |
| 831 | * be any stations. | ||
| 825 | */ | 832 | */ |
| 826 | flushed = sta_info_flush(sdata); | 833 | flushed = sta_info_flush(sdata); |
| 827 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 834 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
| 828 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 835 | ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
| 836 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); | ||
| 829 | 837 | ||
| 830 | /* don't count this interface for promisc/allmulti while it is down */ | 838 | /* don't count this interface for promisc/allmulti while it is down */ |
| 831 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 839 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 2291cd730091..a907f2d5c12d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
| @@ -58,6 +58,22 @@ static void assert_key_lock(struct ieee80211_local *local) | |||
| 58 | lockdep_assert_held(&local->key_mtx); | 58 | lockdep_assert_held(&local->key_mtx); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | static void | ||
| 62 | update_vlan_tailroom_need_count(struct ieee80211_sub_if_data *sdata, int delta) | ||
| 63 | { | ||
| 64 | struct ieee80211_sub_if_data *vlan; | ||
| 65 | |||
| 66 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
| 67 | return; | ||
| 68 | |||
| 69 | mutex_lock(&sdata->local->mtx); | ||
| 70 | |||
| 71 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
| 72 | vlan->crypto_tx_tailroom_needed_cnt += delta; | ||
| 73 | |||
| 74 | mutex_unlock(&sdata->local->mtx); | ||
| 75 | } | ||
| 76 | |||
| 61 | static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) | 77 | static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) |
| 62 | { | 78 | { |
| 63 | /* | 79 | /* |
| @@ -79,6 +95,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) | |||
| 79 | * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net | 95 | * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net |
| 80 | */ | 96 | */ |
| 81 | 97 | ||
| 98 | update_vlan_tailroom_need_count(sdata, 1); | ||
| 99 | |||
| 82 | if (!sdata->crypto_tx_tailroom_needed_cnt++) { | 100 | if (!sdata->crypto_tx_tailroom_needed_cnt++) { |
| 83 | /* | 101 | /* |
| 84 | * Flush all XMIT packets currently using HW encryption or no | 102 | * Flush all XMIT packets currently using HW encryption or no |
| @@ -88,6 +106,15 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) | |||
| 88 | } | 106 | } |
| 89 | } | 107 | } |
| 90 | 108 | ||
| 109 | static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata, | ||
| 110 | int delta) | ||
| 111 | { | ||
| 112 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt < delta); | ||
| 113 | |||
| 114 | update_vlan_tailroom_need_count(sdata, -delta); | ||
| 115 | sdata->crypto_tx_tailroom_needed_cnt -= delta; | ||
| 116 | } | ||
| 117 | |||
| 91 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 118 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
| 92 | { | 119 | { |
| 93 | struct ieee80211_sub_if_data *sdata; | 120 | struct ieee80211_sub_if_data *sdata; |
| @@ -144,7 +171,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
| 144 | 171 | ||
| 145 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | 172 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 146 | (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) | 173 | (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) |
| 147 | sdata->crypto_tx_tailroom_needed_cnt--; | 174 | decrease_tailroom_need_count(sdata, 1); |
| 148 | 175 | ||
| 149 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && | 176 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && |
| 150 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)); | 177 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)); |
| @@ -541,7 +568,7 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key, | |||
| 541 | schedule_delayed_work(&sdata->dec_tailroom_needed_wk, | 568 | schedule_delayed_work(&sdata->dec_tailroom_needed_wk, |
| 542 | HZ/2); | 569 | HZ/2); |
| 543 | } else { | 570 | } else { |
| 544 | sdata->crypto_tx_tailroom_needed_cnt--; | 571 | decrease_tailroom_need_count(sdata, 1); |
| 545 | } | 572 | } |
| 546 | } | 573 | } |
| 547 | 574 | ||
| @@ -631,6 +658,7 @@ void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) | |||
| 631 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | 658 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) |
| 632 | { | 659 | { |
| 633 | struct ieee80211_key *key; | 660 | struct ieee80211_key *key; |
| 661 | struct ieee80211_sub_if_data *vlan; | ||
| 634 | 662 | ||
| 635 | ASSERT_RTNL(); | 663 | ASSERT_RTNL(); |
| 636 | 664 | ||
| @@ -639,7 +667,14 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | |||
| 639 | 667 | ||
| 640 | mutex_lock(&sdata->local->key_mtx); | 668 | mutex_lock(&sdata->local->key_mtx); |
| 641 | 669 | ||
| 642 | sdata->crypto_tx_tailroom_needed_cnt = 0; | 670 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || |
| 671 | sdata->crypto_tx_tailroom_pending_dec); | ||
| 672 | |||
| 673 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
| 674 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
| 675 | WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt || | ||
| 676 | vlan->crypto_tx_tailroom_pending_dec); | ||
| 677 | } | ||
| 643 | 678 | ||
| 644 | list_for_each_entry(key, &sdata->key_list, list) { | 679 | list_for_each_entry(key, &sdata->key_list, list) { |
| 645 | increment_tailroom_need_count(sdata); | 680 | increment_tailroom_need_count(sdata); |
| @@ -649,6 +684,22 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | |||
| 649 | mutex_unlock(&sdata->local->key_mtx); | 684 | mutex_unlock(&sdata->local->key_mtx); |
| 650 | } | 685 | } |
| 651 | 686 | ||
| 687 | void ieee80211_reset_crypto_tx_tailroom(struct ieee80211_sub_if_data *sdata) | ||
| 688 | { | ||
| 689 | struct ieee80211_sub_if_data *vlan; | ||
| 690 | |||
| 691 | mutex_lock(&sdata->local->key_mtx); | ||
| 692 | |||
| 693 | sdata->crypto_tx_tailroom_needed_cnt = 0; | ||
| 694 | |||
| 695 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
| 696 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
| 697 | vlan->crypto_tx_tailroom_needed_cnt = 0; | ||
| 698 | } | ||
| 699 | |||
| 700 | mutex_unlock(&sdata->local->key_mtx); | ||
| 701 | } | ||
| 702 | |||
| 652 | void ieee80211_iter_keys(struct ieee80211_hw *hw, | 703 | void ieee80211_iter_keys(struct ieee80211_hw *hw, |
| 653 | struct ieee80211_vif *vif, | 704 | struct ieee80211_vif *vif, |
| 654 | void (*iter)(struct ieee80211_hw *hw, | 705 | void (*iter)(struct ieee80211_hw *hw, |
| @@ -688,8 +739,8 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, | |||
| 688 | { | 739 | { |
| 689 | struct ieee80211_key *key, *tmp; | 740 | struct ieee80211_key *key, *tmp; |
| 690 | 741 | ||
| 691 | sdata->crypto_tx_tailroom_needed_cnt -= | 742 | decrease_tailroom_need_count(sdata, |
| 692 | sdata->crypto_tx_tailroom_pending_dec; | 743 | sdata->crypto_tx_tailroom_pending_dec); |
| 693 | sdata->crypto_tx_tailroom_pending_dec = 0; | 744 | sdata->crypto_tx_tailroom_pending_dec = 0; |
| 694 | 745 | ||
| 695 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 746 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
| @@ -709,6 +760,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, | |||
| 709 | { | 760 | { |
| 710 | struct ieee80211_local *local = sdata->local; | 761 | struct ieee80211_local *local = sdata->local; |
| 711 | struct ieee80211_sub_if_data *vlan; | 762 | struct ieee80211_sub_if_data *vlan; |
| 763 | struct ieee80211_sub_if_data *master; | ||
| 712 | struct ieee80211_key *key, *tmp; | 764 | struct ieee80211_key *key, *tmp; |
| 713 | LIST_HEAD(keys); | 765 | LIST_HEAD(keys); |
| 714 | 766 | ||
| @@ -728,8 +780,20 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, | |||
| 728 | list_for_each_entry_safe(key, tmp, &keys, list) | 780 | list_for_each_entry_safe(key, tmp, &keys, list) |
| 729 | __ieee80211_key_destroy(key, false); | 781 | __ieee80211_key_destroy(key, false); |
| 730 | 782 | ||
| 731 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | 783 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
| 732 | sdata->crypto_tx_tailroom_pending_dec); | 784 | if (sdata->bss) { |
| 785 | master = container_of(sdata->bss, | ||
| 786 | struct ieee80211_sub_if_data, | ||
| 787 | u.ap); | ||
| 788 | |||
| 789 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt != | ||
| 790 | master->crypto_tx_tailroom_needed_cnt); | ||
| 791 | } | ||
| 792 | } else { | ||
| 793 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | ||
| 794 | sdata->crypto_tx_tailroom_pending_dec); | ||
| 795 | } | ||
| 796 | |||
| 733 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 797 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
| 734 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 798 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
| 735 | WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt || | 799 | WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt || |
| @@ -793,8 +857,8 @@ void ieee80211_delayed_tailroom_dec(struct work_struct *wk) | |||
| 793 | */ | 857 | */ |
| 794 | 858 | ||
| 795 | mutex_lock(&sdata->local->key_mtx); | 859 | mutex_lock(&sdata->local->key_mtx); |
| 796 | sdata->crypto_tx_tailroom_needed_cnt -= | 860 | decrease_tailroom_need_count(sdata, |
| 797 | sdata->crypto_tx_tailroom_pending_dec; | 861 | sdata->crypto_tx_tailroom_pending_dec); |
| 798 | sdata->crypto_tx_tailroom_pending_dec = 0; | 862 | sdata->crypto_tx_tailroom_pending_dec = 0; |
| 799 | mutex_unlock(&sdata->local->key_mtx); | 863 | mutex_unlock(&sdata->local->key_mtx); |
| 800 | } | 864 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index c5a31835be0e..96557dd1e77d 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
| @@ -161,6 +161,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, | |||
| 161 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | 161 | void ieee80211_free_sta_keys(struct ieee80211_local *local, |
| 162 | struct sta_info *sta); | 162 | struct sta_info *sta); |
| 163 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 163 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
| 164 | void ieee80211_reset_crypto_tx_tailroom(struct ieee80211_sub_if_data *sdata); | ||
| 164 | 165 | ||
| 165 | #define key_mtx_dereference(local, ref) \ | 166 | #define key_mtx_dereference(local, ref) \ |
| 166 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) | 167 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 260eed45b6d2..5793f75c5ffd 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -2121,7 +2121,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
| 2121 | /* deliver to local stack */ | 2121 | /* deliver to local stack */ |
| 2122 | skb->protocol = eth_type_trans(skb, dev); | 2122 | skb->protocol = eth_type_trans(skb, dev); |
| 2123 | memset(skb->cb, 0, sizeof(skb->cb)); | 2123 | memset(skb->cb, 0, sizeof(skb->cb)); |
| 2124 | if (rx->local->napi) | 2124 | if (!(rx->flags & IEEE80211_RX_REORDER_TIMER) && |
| 2125 | rx->local->napi) | ||
| 2125 | napi_gro_receive(rx->local->napi, skb); | 2126 | napi_gro_receive(rx->local->napi, skb); |
| 2126 | else | 2127 | else |
| 2127 | netif_receive_skb(skb); | 2128 | netif_receive_skb(skb); |
| @@ -3231,7 +3232,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
| 3231 | /* This is OK -- must be QoS data frame */ | 3232 | /* This is OK -- must be QoS data frame */ |
| 3232 | .security_idx = tid, | 3233 | .security_idx = tid, |
| 3233 | .seqno_idx = tid, | 3234 | .seqno_idx = tid, |
| 3234 | .flags = 0, | 3235 | .flags = IEEE80211_RX_REORDER_TIMER, |
| 3235 | }; | 3236 | }; |
| 3236 | struct tid_ampdu_rx *tid_agg_rx; | 3237 | struct tid_ampdu_rx *tid_agg_rx; |
| 3237 | 3238 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 12971b71d0fa..2880f2ae99ab 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | 66 | ||
| 67 | static const struct rhashtable_params sta_rht_params = { | 67 | static const struct rhashtable_params sta_rht_params = { |
| 68 | .nelem_hint = 3, /* start small */ | 68 | .nelem_hint = 3, /* start small */ |
| 69 | .automatic_shrinking = true, | ||
| 69 | .head_offset = offsetof(struct sta_info, hash_node), | 70 | .head_offset = offsetof(struct sta_info, hash_node), |
| 70 | .key_offset = offsetof(struct sta_info, sta.addr), | 71 | .key_offset = offsetof(struct sta_info, sta.addr), |
| 71 | .key_len = ETH_ALEN, | 72 | .key_len = ETH_ALEN, |
| @@ -157,8 +158,24 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 157 | const u8 *addr) | 158 | const u8 *addr) |
| 158 | { | 159 | { |
| 159 | struct ieee80211_local *local = sdata->local; | 160 | struct ieee80211_local *local = sdata->local; |
| 161 | struct sta_info *sta; | ||
| 162 | struct rhash_head *tmp; | ||
| 163 | const struct bucket_table *tbl; | ||
| 164 | |||
| 165 | rcu_read_lock(); | ||
| 166 | tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash); | ||
| 160 | 167 | ||
| 161 | return rhashtable_lookup_fast(&local->sta_hash, addr, sta_rht_params); | 168 | for_each_sta_info(local, tbl, addr, sta, tmp) { |
| 169 | if (sta->sdata == sdata) { | ||
| 170 | rcu_read_unlock(); | ||
| 171 | /* this is safe as the caller must already hold | ||
| 172 | * another rcu read section or the mutex | ||
| 173 | */ | ||
| 174 | return sta; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | rcu_read_unlock(); | ||
| 178 | return NULL; | ||
| 162 | } | 179 | } |
| 163 | 180 | ||
| 164 | /* | 181 | /* |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 79412f16b61d..b864ebc6ab8f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -2023,6 +2023,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 2023 | 2023 | ||
| 2024 | /* add back keys */ | 2024 | /* add back keys */ |
| 2025 | list_for_each_entry(sdata, &local->interfaces, list) | 2025 | list_for_each_entry(sdata, &local->interfaces, list) |
| 2026 | ieee80211_reset_crypto_tx_tailroom(sdata); | ||
| 2027 | |||
| 2028 | list_for_each_entry(sdata, &local->interfaces, list) | ||
| 2026 | if (ieee80211_sdata_running(sdata)) | 2029 | if (ieee80211_sdata_running(sdata)) |
| 2027 | ieee80211_enable_keys(sdata); | 2030 | ieee80211_enable_keys(sdata); |
| 2028 | 2031 | ||
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index a4220e92f0cc..efa3f48f1ec5 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
| @@ -98,8 +98,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, | |||
| 98 | 98 | ||
| 99 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 99 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
| 100 | 100 | ||
| 101 | if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN || | 101 | if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) |
| 102 | skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) | ||
| 103 | return NULL; | 102 | return NULL; |
| 104 | 103 | ||
| 105 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 104 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
| @@ -167,6 +166,9 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, | |||
| 167 | size_t len; | 166 | size_t len; |
| 168 | u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; | 167 | u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; |
| 169 | 168 | ||
| 169 | if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN)) | ||
| 170 | return -1; | ||
| 171 | |||
| 170 | iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); | 172 | iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); |
| 171 | if (!iv) | 173 | if (!iv) |
| 172 | return -1; | 174 | return -1; |
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 5d9f68c75e5f..70be9c799f8a 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c | |||
| @@ -22,13 +22,14 @@ | |||
| 22 | 22 | ||
| 23 | static struct net_device * | 23 | static struct net_device * |
| 24 | ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, | 24 | ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, |
| 25 | const char *name, int type) | 25 | const char *name, |
| 26 | unsigned char name_assign_type, int type) | ||
| 26 | { | 27 | { |
| 27 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); | 28 | struct ieee802154_local *local = wpan_phy_priv(wpan_phy); |
| 28 | struct net_device *dev; | 29 | struct net_device *dev; |
| 29 | 30 | ||
| 30 | rtnl_lock(); | 31 | rtnl_lock(); |
| 31 | dev = ieee802154_if_add(local, name, type, | 32 | dev = ieee802154_if_add(local, name, name_assign_type, type, |
| 32 | cpu_to_le64(0x0000000000000000ULL)); | 33 | cpu_to_le64(0x0000000000000000ULL)); |
| 33 | rtnl_unlock(); | 34 | rtnl_unlock(); |
| 34 | 35 | ||
| @@ -45,12 +46,14 @@ static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, | |||
| 45 | 46 | ||
| 46 | static int | 47 | static int |
| 47 | ieee802154_add_iface(struct wpan_phy *phy, const char *name, | 48 | ieee802154_add_iface(struct wpan_phy *phy, const char *name, |
| 49 | unsigned char name_assign_type, | ||
| 48 | enum nl802154_iftype type, __le64 extended_addr) | 50 | enum nl802154_iftype type, __le64 extended_addr) |
| 49 | { | 51 | { |
| 50 | struct ieee802154_local *local = wpan_phy_priv(phy); | 52 | struct ieee802154_local *local = wpan_phy_priv(phy); |
| 51 | struct net_device *err; | 53 | struct net_device *err; |
| 52 | 54 | ||
| 53 | err = ieee802154_if_add(local, name, type, extended_addr); | 55 | err = ieee802154_if_add(local, name, name_assign_type, type, |
| 56 | extended_addr); | ||
| 54 | return PTR_ERR_OR_ZERO(err); | 57 | return PTR_ERR_OR_ZERO(err); |
| 55 | } | 58 | } |
| 56 | 59 | ||
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index bebd70ffc7a3..127ba18386fc 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h | |||
| @@ -182,7 +182,8 @@ void ieee802154_iface_exit(void); | |||
| 182 | void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); | 182 | void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); |
| 183 | struct net_device * | 183 | struct net_device * |
| 184 | ieee802154_if_add(struct ieee802154_local *local, const char *name, | 184 | ieee802154_if_add(struct ieee802154_local *local, const char *name, |
| 185 | enum nl802154_iftype type, __le64 extended_addr); | 185 | unsigned char name_assign_type, enum nl802154_iftype type, |
| 186 | __le64 extended_addr); | ||
| 186 | void ieee802154_remove_interfaces(struct ieee802154_local *local); | 187 | void ieee802154_remove_interfaces(struct ieee802154_local *local); |
| 187 | 188 | ||
| 188 | #endif /* __IEEE802154_I_H */ | 189 | #endif /* __IEEE802154_I_H */ |
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 38b56f9d9386..91b75abbd1a1 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c | |||
| @@ -522,7 +522,8 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, | |||
| 522 | 522 | ||
| 523 | struct net_device * | 523 | struct net_device * |
| 524 | ieee802154_if_add(struct ieee802154_local *local, const char *name, | 524 | ieee802154_if_add(struct ieee802154_local *local, const char *name, |
| 525 | enum nl802154_iftype type, __le64 extended_addr) | 525 | unsigned char name_assign_type, enum nl802154_iftype type, |
| 526 | __le64 extended_addr) | ||
| 526 | { | 527 | { |
| 527 | struct net_device *ndev = NULL; | 528 | struct net_device *ndev = NULL; |
| 528 | struct ieee802154_sub_if_data *sdata = NULL; | 529 | struct ieee802154_sub_if_data *sdata = NULL; |
| @@ -531,7 +532,7 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, | |||
| 531 | ASSERT_RTNL(); | 532 | ASSERT_RTNL(); |
| 532 | 533 | ||
| 533 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, | 534 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, |
| 534 | NET_NAME_UNKNOWN, ieee802154_if_setup); | 535 | name_assign_type, ieee802154_if_setup); |
| 535 | if (!ndev) | 536 | if (!ndev) |
| 536 | return ERR_PTR(-ENOMEM); | 537 | return ERR_PTR(-ENOMEM); |
| 537 | 538 | ||
diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index dcf73958133a..5b2be12832e6 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c | |||
| @@ -134,7 +134,7 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) | |||
| 134 | for (i = 0; i < ARRAY_SIZE(key->tfm); i++) { | 134 | for (i = 0; i < ARRAY_SIZE(key->tfm); i++) { |
| 135 | key->tfm[i] = crypto_alloc_aead("ccm(aes)", 0, | 135 | key->tfm[i] = crypto_alloc_aead("ccm(aes)", 0, |
| 136 | CRYPTO_ALG_ASYNC); | 136 | CRYPTO_ALG_ASYNC); |
| 137 | if (!key->tfm[i]) | 137 | if (IS_ERR(key->tfm[i])) |
| 138 | goto err_tfm; | 138 | goto err_tfm; |
| 139 | if (crypto_aead_setkey(key->tfm[i], template->key, | 139 | if (crypto_aead_setkey(key->tfm[i], template->key, |
| 140 | IEEE802154_LLSEC_KEY_SIZE)) | 140 | IEEE802154_LLSEC_KEY_SIZE)) |
| @@ -144,7 +144,7 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | key->tfm0 = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); | 146 | key->tfm0 = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); |
| 147 | if (!key->tfm0) | 147 | if (IS_ERR(key->tfm0)) |
| 148 | goto err_tfm; | 148 | goto err_tfm; |
| 149 | 149 | ||
| 150 | if (crypto_blkcipher_setkey(key->tfm0, template->key, | 150 | if (crypto_blkcipher_setkey(key->tfm0, template->key, |
diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 8500378c8318..08cb32dc8fd3 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c | |||
| @@ -161,18 +161,21 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) | |||
| 161 | 161 | ||
| 162 | rtnl_lock(); | 162 | rtnl_lock(); |
| 163 | 163 | ||
| 164 | dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE, | 164 | dev = ieee802154_if_add(local, "wpan%d", NET_NAME_ENUM, |
| 165 | NL802154_IFTYPE_NODE, | ||
| 165 | cpu_to_le64(0x0000000000000000ULL)); | 166 | cpu_to_le64(0x0000000000000000ULL)); |
| 166 | if (IS_ERR(dev)) { | 167 | if (IS_ERR(dev)) { |
| 167 | rtnl_unlock(); | 168 | rtnl_unlock(); |
| 168 | rc = PTR_ERR(dev); | 169 | rc = PTR_ERR(dev); |
| 169 | goto out_wq; | 170 | goto out_phy; |
| 170 | } | 171 | } |
| 171 | 172 | ||
| 172 | rtnl_unlock(); | 173 | rtnl_unlock(); |
| 173 | 174 | ||
| 174 | return 0; | 175 | return 0; |
| 175 | 176 | ||
| 177 | out_phy: | ||
| 178 | wpan_phy_unregister(local->phy); | ||
| 176 | out_wq: | 179 | out_wq: |
| 177 | destroy_workqueue(local->workqueue); | 180 | destroy_workqueue(local->workqueue); |
| 178 | out: | 181 | out: |
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index db8a2ea6d4de..1f93a5978f2a 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
| @@ -53,6 +53,11 @@ static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index) | |||
| 53 | return rt; | 53 | return rt; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev) | ||
| 57 | { | ||
| 58 | return rcu_dereference_rtnl(dev->mpls_ptr); | ||
| 59 | } | ||
| 60 | |||
| 56 | static bool mpls_output_possible(const struct net_device *dev) | 61 | static bool mpls_output_possible(const struct net_device *dev) |
| 57 | { | 62 | { |
| 58 | return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev); | 63 | return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev); |
| @@ -136,6 +141,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
| 136 | struct mpls_route *rt; | 141 | struct mpls_route *rt; |
| 137 | struct mpls_entry_decoded dec; | 142 | struct mpls_entry_decoded dec; |
| 138 | struct net_device *out_dev; | 143 | struct net_device *out_dev; |
| 144 | struct mpls_dev *mdev; | ||
| 139 | unsigned int hh_len; | 145 | unsigned int hh_len; |
| 140 | unsigned int new_header_size; | 146 | unsigned int new_header_size; |
| 141 | unsigned int mtu; | 147 | unsigned int mtu; |
| @@ -143,6 +149,10 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
| 143 | 149 | ||
| 144 | /* Careful this entire function runs inside of an rcu critical section */ | 150 | /* Careful this entire function runs inside of an rcu critical section */ |
| 145 | 151 | ||
| 152 | mdev = mpls_dev_get(dev); | ||
| 153 | if (!mdev || !mdev->input_enabled) | ||
| 154 | goto drop; | ||
| 155 | |||
| 146 | if (skb->pkt_type != PACKET_HOST) | 156 | if (skb->pkt_type != PACKET_HOST) |
| 147 | goto drop; | 157 | goto drop; |
| 148 | 158 | ||
| @@ -352,9 +362,9 @@ static int mpls_route_add(struct mpls_route_config *cfg) | |||
| 352 | if (!dev) | 362 | if (!dev) |
| 353 | goto errout; | 363 | goto errout; |
| 354 | 364 | ||
| 355 | /* For now just support ethernet devices */ | 365 | /* Ensure this is a supported device */ |
| 356 | err = -EINVAL; | 366 | err = -EINVAL; |
| 357 | if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK)) | 367 | if (!mpls_dev_get(dev)) |
| 358 | goto errout; | 368 | goto errout; |
| 359 | 369 | ||
| 360 | err = -EINVAL; | 370 | err = -EINVAL; |
| @@ -428,10 +438,89 @@ errout: | |||
| 428 | return err; | 438 | return err; |
| 429 | } | 439 | } |
| 430 | 440 | ||
| 441 | #define MPLS_PERDEV_SYSCTL_OFFSET(field) \ | ||
| 442 | (&((struct mpls_dev *)0)->field) | ||
| 443 | |||
| 444 | static const struct ctl_table mpls_dev_table[] = { | ||
| 445 | { | ||
| 446 | .procname = "input", | ||
| 447 | .maxlen = sizeof(int), | ||
| 448 | .mode = 0644, | ||
| 449 | .proc_handler = proc_dointvec, | ||
| 450 | .data = MPLS_PERDEV_SYSCTL_OFFSET(input_enabled), | ||
| 451 | }, | ||
| 452 | { } | ||
| 453 | }; | ||
| 454 | |||
| 455 | static int mpls_dev_sysctl_register(struct net_device *dev, | ||
| 456 | struct mpls_dev *mdev) | ||
| 457 | { | ||
| 458 | char path[sizeof("net/mpls/conf/") + IFNAMSIZ]; | ||
| 459 | struct ctl_table *table; | ||
| 460 | int i; | ||
| 461 | |||
| 462 | table = kmemdup(&mpls_dev_table, sizeof(mpls_dev_table), GFP_KERNEL); | ||
| 463 | if (!table) | ||
| 464 | goto out; | ||
| 465 | |||
| 466 | /* Table data contains only offsets relative to the base of | ||
| 467 | * the mdev at this point, so make them absolute. | ||
| 468 | */ | ||
| 469 | for (i = 0; i < ARRAY_SIZE(mpls_dev_table); i++) | ||
| 470 | table[i].data = (char *)mdev + (uintptr_t)table[i].data; | ||
| 471 | |||
| 472 | snprintf(path, sizeof(path), "net/mpls/conf/%s", dev->name); | ||
| 473 | |||
| 474 | mdev->sysctl = register_net_sysctl(dev_net(dev), path, table); | ||
| 475 | if (!mdev->sysctl) | ||
| 476 | goto free; | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | |||
| 480 | free: | ||
| 481 | kfree(table); | ||
| 482 | out: | ||
| 483 | return -ENOBUFS; | ||
| 484 | } | ||
| 485 | |||
| 486 | static void mpls_dev_sysctl_unregister(struct mpls_dev *mdev) | ||
| 487 | { | ||
| 488 | struct ctl_table *table; | ||
| 489 | |||
| 490 | table = mdev->sysctl->ctl_table_arg; | ||
| 491 | unregister_net_sysctl_table(mdev->sysctl); | ||
| 492 | kfree(table); | ||
| 493 | } | ||
| 494 | |||
| 495 | static struct mpls_dev *mpls_add_dev(struct net_device *dev) | ||
| 496 | { | ||
| 497 | struct mpls_dev *mdev; | ||
| 498 | int err = -ENOMEM; | ||
| 499 | |||
| 500 | ASSERT_RTNL(); | ||
| 501 | |||
| 502 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | ||
| 503 | if (!mdev) | ||
| 504 | return ERR_PTR(err); | ||
| 505 | |||
| 506 | err = mpls_dev_sysctl_register(dev, mdev); | ||
| 507 | if (err) | ||
| 508 | goto free; | ||
| 509 | |||
| 510 | rcu_assign_pointer(dev->mpls_ptr, mdev); | ||
| 511 | |||
| 512 | return mdev; | ||
| 513 | |||
| 514 | free: | ||
| 515 | kfree(mdev); | ||
| 516 | return ERR_PTR(err); | ||
| 517 | } | ||
| 518 | |||
| 431 | static void mpls_ifdown(struct net_device *dev) | 519 | static void mpls_ifdown(struct net_device *dev) |
| 432 | { | 520 | { |
| 433 | struct mpls_route __rcu **platform_label; | 521 | struct mpls_route __rcu **platform_label; |
| 434 | struct net *net = dev_net(dev); | 522 | struct net *net = dev_net(dev); |
| 523 | struct mpls_dev *mdev; | ||
| 435 | unsigned index; | 524 | unsigned index; |
| 436 | 525 | ||
| 437 | platform_label = rtnl_dereference(net->mpls.platform_label); | 526 | platform_label = rtnl_dereference(net->mpls.platform_label); |
| @@ -443,17 +532,49 @@ static void mpls_ifdown(struct net_device *dev) | |||
| 443 | continue; | 532 | continue; |
| 444 | rt->rt_dev = NULL; | 533 | rt->rt_dev = NULL; |
| 445 | } | 534 | } |
| 535 | |||
| 536 | mdev = mpls_dev_get(dev); | ||
| 537 | if (!mdev) | ||
| 538 | return; | ||
| 539 | |||
| 540 | mpls_dev_sysctl_unregister(mdev); | ||
| 541 | |||
| 542 | RCU_INIT_POINTER(dev->mpls_ptr, NULL); | ||
| 543 | |||
| 544 | kfree_rcu(mdev, rcu); | ||
| 446 | } | 545 | } |
| 447 | 546 | ||
| 448 | static int mpls_dev_notify(struct notifier_block *this, unsigned long event, | 547 | static int mpls_dev_notify(struct notifier_block *this, unsigned long event, |
| 449 | void *ptr) | 548 | void *ptr) |
| 450 | { | 549 | { |
| 451 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 550 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
| 551 | struct mpls_dev *mdev; | ||
| 452 | 552 | ||
| 453 | switch(event) { | 553 | switch(event) { |
| 554 | case NETDEV_REGISTER: | ||
| 555 | /* For now just support ethernet devices */ | ||
| 556 | if ((dev->type == ARPHRD_ETHER) || | ||
| 557 | (dev->type == ARPHRD_LOOPBACK)) { | ||
| 558 | mdev = mpls_add_dev(dev); | ||
| 559 | if (IS_ERR(mdev)) | ||
| 560 | return notifier_from_errno(PTR_ERR(mdev)); | ||
| 561 | } | ||
| 562 | break; | ||
| 563 | |||
| 454 | case NETDEV_UNREGISTER: | 564 | case NETDEV_UNREGISTER: |
| 455 | mpls_ifdown(dev); | 565 | mpls_ifdown(dev); |
| 456 | break; | 566 | break; |
| 567 | case NETDEV_CHANGENAME: | ||
| 568 | mdev = mpls_dev_get(dev); | ||
| 569 | if (mdev) { | ||
| 570 | int err; | ||
| 571 | |||
| 572 | mpls_dev_sysctl_unregister(mdev); | ||
| 573 | err = mpls_dev_sysctl_register(dev, mdev); | ||
| 574 | if (err) | ||
| 575 | return notifier_from_errno(err); | ||
| 576 | } | ||
| 577 | break; | ||
| 457 | } | 578 | } |
| 458 | return NOTIFY_OK; | 579 | return NOTIFY_OK; |
| 459 | } | 580 | } |
| @@ -536,6 +657,15 @@ int nla_get_labels(const struct nlattr *nla, | |||
| 536 | if ((dec.bos != bos) || dec.ttl || dec.tc) | 657 | if ((dec.bos != bos) || dec.ttl || dec.tc) |
| 537 | return -EINVAL; | 658 | return -EINVAL; |
| 538 | 659 | ||
| 660 | switch (dec.label) { | ||
| 661 | case MPLS_LABEL_IMPLNULL: | ||
| 662 | /* RFC3032: This is a label that an LSR may | ||
| 663 | * assign and distribute, but which never | ||
| 664 | * actually appears in the encapsulation. | ||
| 665 | */ | ||
| 666 | return -EINVAL; | ||
| 667 | } | ||
| 668 | |||
| 539 | label[i] = dec.label; | 669 | label[i] = dec.label; |
| 540 | } | 670 | } |
| 541 | *labels = nla_labels; | 671 | *labels = nla_labels; |
| @@ -816,7 +946,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
| 816 | } | 946 | } |
| 817 | 947 | ||
| 818 | /* In case the predefined labels need to be populated */ | 948 | /* In case the predefined labels need to be populated */ |
| 819 | if (limit > LABEL_IPV4_EXPLICIT_NULL) { | 949 | if (limit > MPLS_LABEL_IPV4NULL) { |
| 820 | struct net_device *lo = net->loopback_dev; | 950 | struct net_device *lo = net->loopback_dev; |
| 821 | rt0 = mpls_rt_alloc(lo->addr_len); | 951 | rt0 = mpls_rt_alloc(lo->addr_len); |
| 822 | if (!rt0) | 952 | if (!rt0) |
| @@ -826,7 +956,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
| 826 | rt0->rt_via_table = NEIGH_LINK_TABLE; | 956 | rt0->rt_via_table = NEIGH_LINK_TABLE; |
| 827 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); | 957 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); |
| 828 | } | 958 | } |
| 829 | if (limit > LABEL_IPV6_EXPLICIT_NULL) { | 959 | if (limit > MPLS_LABEL_IPV6NULL) { |
| 830 | struct net_device *lo = net->loopback_dev; | 960 | struct net_device *lo = net->loopback_dev; |
| 831 | rt2 = mpls_rt_alloc(lo->addr_len); | 961 | rt2 = mpls_rt_alloc(lo->addr_len); |
| 832 | if (!rt2) | 962 | if (!rt2) |
| @@ -854,15 +984,15 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
| 854 | memcpy(labels, old, cp_size); | 984 | memcpy(labels, old, cp_size); |
| 855 | 985 | ||
| 856 | /* If needed set the predefined labels */ | 986 | /* If needed set the predefined labels */ |
| 857 | if ((old_limit <= LABEL_IPV6_EXPLICIT_NULL) && | 987 | if ((old_limit <= MPLS_LABEL_IPV6NULL) && |
| 858 | (limit > LABEL_IPV6_EXPLICIT_NULL)) { | 988 | (limit > MPLS_LABEL_IPV6NULL)) { |
| 859 | RCU_INIT_POINTER(labels[LABEL_IPV6_EXPLICIT_NULL], rt2); | 989 | RCU_INIT_POINTER(labels[MPLS_LABEL_IPV6NULL], rt2); |
| 860 | rt2 = NULL; | 990 | rt2 = NULL; |
| 861 | } | 991 | } |
| 862 | 992 | ||
| 863 | if ((old_limit <= LABEL_IPV4_EXPLICIT_NULL) && | 993 | if ((old_limit <= MPLS_LABEL_IPV4NULL) && |
| 864 | (limit > LABEL_IPV4_EXPLICIT_NULL)) { | 994 | (limit > MPLS_LABEL_IPV4NULL)) { |
| 865 | RCU_INIT_POINTER(labels[LABEL_IPV4_EXPLICIT_NULL], rt0); | 995 | RCU_INIT_POINTER(labels[MPLS_LABEL_IPV4NULL], rt0); |
| 866 | rt0 = NULL; | 996 | rt0 = NULL; |
| 867 | } | 997 | } |
| 868 | 998 | ||
| @@ -912,7 +1042,7 @@ static int mpls_platform_labels(struct ctl_table *table, int write, | |||
| 912 | return ret; | 1042 | return ret; |
| 913 | } | 1043 | } |
| 914 | 1044 | ||
| 915 | static struct ctl_table mpls_table[] = { | 1045 | static const struct ctl_table mpls_table[] = { |
| 916 | { | 1046 | { |
| 917 | .procname = "platform_labels", | 1047 | .procname = "platform_labels", |
| 918 | .data = NULL, | 1048 | .data = NULL, |
diff --git a/net/mpls/internal.h b/net/mpls/internal.h index fb6de92052c4..8cabeb5a1cb9 100644 --- a/net/mpls/internal.h +++ b/net/mpls/internal.h | |||
| @@ -1,16 +1,6 @@ | |||
| 1 | #ifndef MPLS_INTERNAL_H | 1 | #ifndef MPLS_INTERNAL_H |
| 2 | #define MPLS_INTERNAL_H | 2 | #define MPLS_INTERNAL_H |
| 3 | 3 | ||
| 4 | #define LABEL_IPV4_EXPLICIT_NULL 0 /* RFC3032 */ | ||
| 5 | #define LABEL_ROUTER_ALERT_LABEL 1 /* RFC3032 */ | ||
| 6 | #define LABEL_IPV6_EXPLICIT_NULL 2 /* RFC3032 */ | ||
| 7 | #define LABEL_IMPLICIT_NULL 3 /* RFC3032 */ | ||
| 8 | #define LABEL_ENTROPY_INDICATOR 7 /* RFC6790 */ | ||
| 9 | #define LABEL_GAL 13 /* RFC5586 */ | ||
| 10 | #define LABEL_OAM_ALERT 14 /* RFC3429 */ | ||
| 11 | #define LABEL_EXTENSION 15 /* RFC7274 */ | ||
| 12 | |||
| 13 | |||
| 14 | struct mpls_shim_hdr { | 4 | struct mpls_shim_hdr { |
| 15 | __be32 label_stack_entry; | 5 | __be32 label_stack_entry; |
| 16 | }; | 6 | }; |
| @@ -22,6 +12,13 @@ struct mpls_entry_decoded { | |||
| 22 | u8 bos; | 12 | u8 bos; |
| 23 | }; | 13 | }; |
| 24 | 14 | ||
| 15 | struct mpls_dev { | ||
| 16 | int input_enabled; | ||
| 17 | |||
| 18 | struct ctl_table_header *sysctl; | ||
| 19 | struct rcu_head rcu; | ||
| 20 | }; | ||
| 21 | |||
| 25 | struct sk_buff; | 22 | struct sk_buff; |
| 26 | 23 | ||
| 27 | static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb) | 24 | static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb) |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index f70e34a68f70..a0f3e6a3c7d1 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -863,6 +863,7 @@ config NETFILTER_XT_TARGET_TPROXY | |||
| 863 | depends on NETFILTER_XTABLES | 863 | depends on NETFILTER_XTABLES |
| 864 | depends on NETFILTER_ADVANCED | 864 | depends on NETFILTER_ADVANCED |
| 865 | depends on (IPV6 || IPV6=n) | 865 | depends on (IPV6 || IPV6=n) |
| 866 | depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n) | ||
| 866 | depends on IP_NF_MANGLE | 867 | depends on IP_NF_MANGLE |
| 867 | select NF_DEFRAG_IPV4 | 868 | select NF_DEFRAG_IPV4 |
| 868 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | 869 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES |
| @@ -1356,6 +1357,7 @@ config NETFILTER_XT_MATCH_SOCKET | |||
| 1356 | depends on NETFILTER_ADVANCED | 1357 | depends on NETFILTER_ADVANCED |
| 1357 | depends on !NF_CONNTRACK || NF_CONNTRACK | 1358 | depends on !NF_CONNTRACK || NF_CONNTRACK |
| 1358 | depends on (IPV6 || IPV6=n) | 1359 | depends on (IPV6 || IPV6=n) |
| 1360 | depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n) | ||
| 1359 | select NF_DEFRAG_IPV4 | 1361 | select NF_DEFRAG_IPV4 |
| 1360 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | 1362 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES |
| 1361 | help | 1363 | help |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 49532672f66d..285eae3a1454 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
| @@ -3823,6 +3823,9 @@ static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | |||
| 3823 | cancel_work_sync(&ipvs->defense_work.work); | 3823 | cancel_work_sync(&ipvs->defense_work.work); |
| 3824 | unregister_net_sysctl_table(ipvs->sysctl_hdr); | 3824 | unregister_net_sysctl_table(ipvs->sysctl_hdr); |
| 3825 | ip_vs_stop_estimator(net, &ipvs->tot_stats); | 3825 | ip_vs_stop_estimator(net, &ipvs->tot_stats); |
| 3826 | |||
| 3827 | if (!net_eq(net, &init_net)) | ||
| 3828 | kfree(ipvs->sysctl_tbl); | ||
| 3826 | } | 3829 | } |
| 3827 | 3830 | ||
| 3828 | #else | 3831 | #else |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 5caa0c41bf26..70383de72054 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
| @@ -202,7 +202,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
| 202 | * sES -> sES :-) | 202 | * sES -> sES :-) |
| 203 | * sFW -> sCW Normal close request answered by ACK. | 203 | * sFW -> sCW Normal close request answered by ACK. |
| 204 | * sCW -> sCW | 204 | * sCW -> sCW |
| 205 | * sLA -> sTW Last ACK detected. | 205 | * sLA -> sTW Last ACK detected (RFC5961 challenged) |
| 206 | * sTW -> sTW Retransmitted last ACK. Remain in the same state. | 206 | * sTW -> sTW Retransmitted last ACK. Remain in the same state. |
| 207 | * sCL -> sCL | 207 | * sCL -> sCL |
| 208 | */ | 208 | */ |
| @@ -261,7 +261,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { | |||
| 261 | * sES -> sES :-) | 261 | * sES -> sES :-) |
| 262 | * sFW -> sCW Normal close request answered by ACK. | 262 | * sFW -> sCW Normal close request answered by ACK. |
| 263 | * sCW -> sCW | 263 | * sCW -> sCW |
| 264 | * sLA -> sTW Last ACK detected. | 264 | * sLA -> sTW Last ACK detected (RFC5961 challenged) |
| 265 | * sTW -> sTW Retransmitted last ACK. | 265 | * sTW -> sTW Retransmitted last ACK. |
| 266 | * sCL -> sCL | 266 | * sCL -> sCL |
| 267 | */ | 267 | */ |
| @@ -906,6 +906,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
| 906 | 1 : ct->proto.tcp.last_win; | 906 | 1 : ct->proto.tcp.last_win; |
| 907 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale = | 907 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale = |
| 908 | ct->proto.tcp.last_wscale; | 908 | ct->proto.tcp.last_wscale; |
| 909 | ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK; | ||
| 909 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags = | 910 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags = |
| 910 | ct->proto.tcp.last_flags; | 911 | ct->proto.tcp.last_flags; |
| 911 | memset(&ct->proto.tcp.seen[dir], 0, | 912 | memset(&ct->proto.tcp.seen[dir], 0, |
| @@ -923,7 +924,9 @@ static int tcp_packet(struct nf_conn *ct, | |||
| 923 | * may be in sync but we are not. In that case, we annotate | 924 | * may be in sync but we are not. In that case, we annotate |
| 924 | * the TCP options and let the packet go through. If it is a | 925 | * the TCP options and let the packet go through. If it is a |
| 925 | * valid SYN packet, the server will reply with a SYN/ACK, and | 926 | * valid SYN packet, the server will reply with a SYN/ACK, and |
| 926 | * then we'll get in sync. Otherwise, the server ignores it. */ | 927 | * then we'll get in sync. Otherwise, the server potentially |
| 928 | * responds with a challenge ACK if implementing RFC5961. | ||
| 929 | */ | ||
| 927 | if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) { | 930 | if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) { |
| 928 | struct ip_ct_tcp_state seen = {}; | 931 | struct ip_ct_tcp_state seen = {}; |
| 929 | 932 | ||
| @@ -939,6 +942,13 @@ static int tcp_packet(struct nf_conn *ct, | |||
| 939 | ct->proto.tcp.last_flags |= | 942 | ct->proto.tcp.last_flags |= |
| 940 | IP_CT_TCP_FLAG_SACK_PERM; | 943 | IP_CT_TCP_FLAG_SACK_PERM; |
| 941 | } | 944 | } |
| 945 | /* Mark the potential for RFC5961 challenge ACK, | ||
| 946 | * this pose a special problem for LAST_ACK state | ||
| 947 | * as ACK is intrepretated as ACKing last FIN. | ||
| 948 | */ | ||
| 949 | if (old_state == TCP_CONNTRACK_LAST_ACK) | ||
| 950 | ct->proto.tcp.last_flags |= | ||
| 951 | IP_CT_EXP_CHALLENGE_ACK; | ||
| 942 | } | 952 | } |
| 943 | spin_unlock_bh(&ct->lock); | 953 | spin_unlock_bh(&ct->lock); |
| 944 | if (LOG_INVALID(net, IPPROTO_TCP)) | 954 | if (LOG_INVALID(net, IPPROTO_TCP)) |
| @@ -970,6 +980,25 @@ static int tcp_packet(struct nf_conn *ct, | |||
| 970 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, | 980 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, |
| 971 | "nf_ct_tcp: invalid state "); | 981 | "nf_ct_tcp: invalid state "); |
| 972 | return -NF_ACCEPT; | 982 | return -NF_ACCEPT; |
| 983 | case TCP_CONNTRACK_TIME_WAIT: | ||
| 984 | /* RFC5961 compliance cause stack to send "challenge-ACK" | ||
| 985 | * e.g. in response to spurious SYNs. Conntrack MUST | ||
| 986 | * not believe this ACK is acking last FIN. | ||
| 987 | */ | ||
| 988 | if (old_state == TCP_CONNTRACK_LAST_ACK && | ||
| 989 | index == TCP_ACK_SET && | ||
| 990 | ct->proto.tcp.last_dir != dir && | ||
| 991 | ct->proto.tcp.last_index == TCP_SYN_SET && | ||
| 992 | (ct->proto.tcp.last_flags & IP_CT_EXP_CHALLENGE_ACK)) { | ||
| 993 | /* Detected RFC5961 challenge ACK */ | ||
| 994 | ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK; | ||
| 995 | spin_unlock_bh(&ct->lock); | ||
| 996 | if (LOG_INVALID(net, IPPROTO_TCP)) | ||
| 997 | nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, | ||
| 998 | "nf_ct_tcp: challenge-ACK ignored "); | ||
| 999 | return NF_ACCEPT; /* Don't change state */ | ||
| 1000 | } | ||
| 1001 | break; | ||
| 973 | case TCP_CONNTRACK_CLOSE: | 1002 | case TCP_CONNTRACK_CLOSE: |
| 974 | if (index == TCP_RST_SET | 1003 | if (index == TCP_RST_SET |
| 975 | && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) | 1004 | && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 78af83bc9c8e..34ded09317e7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -4340,7 +4340,6 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
| 4340 | case NFT_CONTINUE: | 4340 | case NFT_CONTINUE: |
| 4341 | case NFT_BREAK: | 4341 | case NFT_BREAK: |
| 4342 | case NFT_RETURN: | 4342 | case NFT_RETURN: |
| 4343 | desc->len = sizeof(data->verdict); | ||
| 4344 | break; | 4343 | break; |
| 4345 | case NFT_JUMP: | 4344 | case NFT_JUMP: |
| 4346 | case NFT_GOTO: | 4345 | case NFT_GOTO: |
| @@ -4355,10 +4354,10 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
| 4355 | 4354 | ||
| 4356 | chain->use++; | 4355 | chain->use++; |
| 4357 | data->verdict.chain = chain; | 4356 | data->verdict.chain = chain; |
| 4358 | desc->len = sizeof(data); | ||
| 4359 | break; | 4357 | break; |
| 4360 | } | 4358 | } |
| 4361 | 4359 | ||
| 4360 | desc->len = sizeof(data->verdict); | ||
| 4362 | desc->type = NFT_DATA_VERDICT; | 4361 | desc->type = NFT_DATA_VERDICT; |
| 4363 | return 0; | 4362 | return 0; |
| 4364 | } | 4363 | } |
| @@ -4473,9 +4472,9 @@ EXPORT_SYMBOL_GPL(nft_data_init); | |||
| 4473 | */ | 4472 | */ |
| 4474 | void nft_data_uninit(const struct nft_data *data, enum nft_data_types type) | 4473 | void nft_data_uninit(const struct nft_data *data, enum nft_data_types type) |
| 4475 | { | 4474 | { |
| 4476 | switch (type) { | 4475 | if (type < NFT_DATA_VERDICT) |
| 4477 | case NFT_DATA_VALUE: | ||
| 4478 | return; | 4476 | return; |
| 4477 | switch (type) { | ||
| 4479 | case NFT_DATA_VERDICT: | 4478 | case NFT_DATA_VERDICT: |
| 4480 | return nft_verdict_uninit(data); | 4479 | return nft_verdict_uninit(data); |
| 4481 | default: | 4480 | default: |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3ad91266c821..4ef1fae8445e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -1073,7 +1073,13 @@ static struct pernet_operations nfnl_log_net_ops = { | |||
| 1073 | 1073 | ||
| 1074 | static int __init nfnetlink_log_init(void) | 1074 | static int __init nfnetlink_log_init(void) |
| 1075 | { | 1075 | { |
| 1076 | int status = -ENOMEM; | 1076 | int status; |
| 1077 | |||
| 1078 | status = register_pernet_subsys(&nfnl_log_net_ops); | ||
| 1079 | if (status < 0) { | ||
| 1080 | pr_err("failed to register pernet ops\n"); | ||
| 1081 | goto out; | ||
| 1082 | } | ||
| 1077 | 1083 | ||
| 1078 | netlink_register_notifier(&nfulnl_rtnl_notifier); | 1084 | netlink_register_notifier(&nfulnl_rtnl_notifier); |
| 1079 | status = nfnetlink_subsys_register(&nfulnl_subsys); | 1085 | status = nfnetlink_subsys_register(&nfulnl_subsys); |
| @@ -1088,28 +1094,23 @@ static int __init nfnetlink_log_init(void) | |||
| 1088 | goto cleanup_subsys; | 1094 | goto cleanup_subsys; |
| 1089 | } | 1095 | } |
| 1090 | 1096 | ||
| 1091 | status = register_pernet_subsys(&nfnl_log_net_ops); | ||
| 1092 | if (status < 0) { | ||
| 1093 | pr_err("failed to register pernet ops\n"); | ||
| 1094 | goto cleanup_logger; | ||
| 1095 | } | ||
| 1096 | return status; | 1097 | return status; |
| 1097 | 1098 | ||
| 1098 | cleanup_logger: | ||
| 1099 | nf_log_unregister(&nfulnl_logger); | ||
| 1100 | cleanup_subsys: | 1099 | cleanup_subsys: |
| 1101 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 1100 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
| 1102 | cleanup_netlink_notifier: | 1101 | cleanup_netlink_notifier: |
| 1103 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | 1102 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
| 1103 | unregister_pernet_subsys(&nfnl_log_net_ops); | ||
| 1104 | out: | ||
| 1104 | return status; | 1105 | return status; |
| 1105 | } | 1106 | } |
| 1106 | 1107 | ||
| 1107 | static void __exit nfnetlink_log_fini(void) | 1108 | static void __exit nfnetlink_log_fini(void) |
| 1108 | { | 1109 | { |
| 1109 | unregister_pernet_subsys(&nfnl_log_net_ops); | ||
| 1110 | nf_log_unregister(&nfulnl_logger); | 1110 | nf_log_unregister(&nfulnl_logger); |
| 1111 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 1111 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
| 1112 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | 1112 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
| 1113 | unregister_pernet_subsys(&nfnl_log_net_ops); | ||
| 1113 | } | 1114 | } |
| 1114 | 1115 | ||
| 1115 | MODULE_DESCRIPTION("netfilter userspace logging"); | 1116 | MODULE_DESCRIPTION("netfilter userspace logging"); |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 0b98c7420239..11c7682fa0ea 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
| @@ -1317,7 +1317,13 @@ static struct pernet_operations nfnl_queue_net_ops = { | |||
| 1317 | 1317 | ||
| 1318 | static int __init nfnetlink_queue_init(void) | 1318 | static int __init nfnetlink_queue_init(void) |
| 1319 | { | 1319 | { |
| 1320 | int status = -ENOMEM; | 1320 | int status; |
| 1321 | |||
| 1322 | status = register_pernet_subsys(&nfnl_queue_net_ops); | ||
| 1323 | if (status < 0) { | ||
| 1324 | pr_err("nf_queue: failed to register pernet ops\n"); | ||
| 1325 | goto out; | ||
| 1326 | } | ||
| 1321 | 1327 | ||
| 1322 | netlink_register_notifier(&nfqnl_rtnl_notifier); | 1328 | netlink_register_notifier(&nfqnl_rtnl_notifier); |
| 1323 | status = nfnetlink_subsys_register(&nfqnl_subsys); | 1329 | status = nfnetlink_subsys_register(&nfqnl_subsys); |
| @@ -1326,19 +1332,13 @@ static int __init nfnetlink_queue_init(void) | |||
| 1326 | goto cleanup_netlink_notifier; | 1332 | goto cleanup_netlink_notifier; |
| 1327 | } | 1333 | } |
| 1328 | 1334 | ||
| 1329 | status = register_pernet_subsys(&nfnl_queue_net_ops); | ||
| 1330 | if (status < 0) { | ||
| 1331 | pr_err("nf_queue: failed to register pernet ops\n"); | ||
| 1332 | goto cleanup_subsys; | ||
| 1333 | } | ||
| 1334 | register_netdevice_notifier(&nfqnl_dev_notifier); | 1335 | register_netdevice_notifier(&nfqnl_dev_notifier); |
| 1335 | nf_register_queue_handler(&nfqh); | 1336 | nf_register_queue_handler(&nfqh); |
| 1336 | return status; | 1337 | return status; |
| 1337 | 1338 | ||
| 1338 | cleanup_subsys: | ||
| 1339 | nfnetlink_subsys_unregister(&nfqnl_subsys); | ||
| 1340 | cleanup_netlink_notifier: | 1339 | cleanup_netlink_notifier: |
| 1341 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | 1340 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); |
| 1341 | out: | ||
| 1342 | return status; | 1342 | return status; |
| 1343 | } | 1343 | } |
| 1344 | 1344 | ||
| @@ -1346,9 +1346,9 @@ static void __exit nfnetlink_queue_fini(void) | |||
| 1346 | { | 1346 | { |
| 1347 | nf_unregister_queue_handler(); | 1347 | nf_unregister_queue_handler(); |
| 1348 | unregister_netdevice_notifier(&nfqnl_dev_notifier); | 1348 | unregister_netdevice_notifier(&nfqnl_dev_notifier); |
| 1349 | unregister_pernet_subsys(&nfnl_queue_net_ops); | ||
| 1350 | nfnetlink_subsys_unregister(&nfqnl_subsys); | 1349 | nfnetlink_subsys_unregister(&nfqnl_subsys); |
| 1351 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); | 1350 | netlink_unregister_notifier(&nfqnl_rtnl_notifier); |
| 1351 | unregister_pernet_subsys(&nfnl_queue_net_ops); | ||
| 1352 | 1352 | ||
| 1353 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1353 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
| 1354 | } | 1354 | } |
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c index 57d3e1af5630..0522fc9bfb0a 100644 --- a/net/netfilter/nft_reject.c +++ b/net/netfilter/nft_reject.c | |||
| @@ -63,6 +63,8 @@ int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
| 63 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) | 63 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) |
| 64 | goto nla_put_failure; | 64 | goto nla_put_failure; |
| 65 | break; | 65 | break; |
| 66 | default: | ||
| 67 | break; | ||
| 66 | } | 68 | } |
| 67 | 69 | ||
| 68 | return 0; | 70 | return 0; |
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 62cabee42fbe..635dbba93d01 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c | |||
| @@ -108,6 +108,8 @@ static int nft_reject_inet_dump(struct sk_buff *skb, | |||
| 108 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) | 108 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) |
| 109 | goto nla_put_failure; | 109 | goto nla_put_failure; |
| 110 | break; | 110 | break; |
| 111 | default: | ||
| 112 | break; | ||
| 111 | } | 113 | } |
| 112 | 114 | ||
| 113 | return 0; | 115 | return 0; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 19909d0786a2..bf6e76643f78 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -89,7 +89,7 @@ static inline int netlink_is_kernel(struct sock *sk) | |||
| 89 | return nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET; | 89 | return nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | struct netlink_table *nl_table; | 92 | struct netlink_table *nl_table __read_mostly; |
| 93 | EXPORT_SYMBOL_GPL(nl_table); | 93 | EXPORT_SYMBOL_GPL(nl_table); |
| 94 | 94 | ||
| 95 | static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); | 95 | static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); |
| @@ -1081,6 +1081,7 @@ static int netlink_insert(struct sock *sk, u32 portid) | |||
| 1081 | if (err) { | 1081 | if (err) { |
| 1082 | if (err == -EEXIST) | 1082 | if (err == -EEXIST) |
| 1083 | err = -EADDRINUSE; | 1083 | err = -EADDRINUSE; |
| 1084 | nlk_sk(sk)->portid = 0; | ||
| 1084 | sock_put(sk); | 1085 | sock_put(sk); |
| 1085 | } | 1086 | } |
| 1086 | 1087 | ||
| @@ -1629,13 +1630,11 @@ static struct sk_buff *netlink_alloc_large_skb(unsigned int size, | |||
| 1629 | if (data == NULL) | 1630 | if (data == NULL) |
| 1630 | return NULL; | 1631 | return NULL; |
| 1631 | 1632 | ||
| 1632 | skb = build_skb(data, size); | 1633 | skb = __build_skb(data, size); |
| 1633 | if (skb == NULL) | 1634 | if (skb == NULL) |
| 1634 | vfree(data); | 1635 | vfree(data); |
| 1635 | else { | 1636 | else |
| 1636 | skb->head_frag = 0; | ||
| 1637 | skb->destructor = netlink_skb_destructor; | 1637 | skb->destructor = netlink_skb_destructor; |
| 1638 | } | ||
| 1639 | 1638 | ||
| 1640 | return skb; | 1639 | return skb; |
| 1641 | } | 1640 | } |
| @@ -3141,7 +3140,6 @@ static const struct rhashtable_params netlink_rhashtable_params = { | |||
| 3141 | .key_len = netlink_compare_arg_len, | 3140 | .key_len = netlink_compare_arg_len, |
| 3142 | .obj_hashfn = netlink_hash, | 3141 | .obj_hashfn = netlink_hash, |
| 3143 | .obj_cmpfn = netlink_compare, | 3142 | .obj_cmpfn = netlink_compare, |
| 3144 | .max_size = 65536, | ||
| 3145 | .automatic_shrinking = true, | 3143 | .automatic_shrinking = true, |
| 3146 | }; | 3144 | }; |
| 3147 | 3145 | ||
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 4776282c6417..33e6d6e2908f 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c | |||
| @@ -125,6 +125,7 @@ static struct vport *netdev_create(const struct vport_parms *parms) | |||
| 125 | if (err) | 125 | if (err) |
| 126 | goto error_master_upper_dev_unlink; | 126 | goto error_master_upper_dev_unlink; |
| 127 | 127 | ||
| 128 | dev_disable_lro(netdev_vport->dev); | ||
| 128 | dev_set_promiscuity(netdev_vport->dev, 1); | 129 | dev_set_promiscuity(netdev_vport->dev, 1); |
| 129 | netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; | 130 | netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; |
| 130 | rtnl_unlock(); | 131 | rtnl_unlock(); |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5102c3cc4eec..b5989c6ee551 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -2311,11 +2311,14 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2311 | tlen = dev->needed_tailroom; | 2311 | tlen = dev->needed_tailroom; |
| 2312 | skb = sock_alloc_send_skb(&po->sk, | 2312 | skb = sock_alloc_send_skb(&po->sk, |
| 2313 | hlen + tlen + sizeof(struct sockaddr_ll), | 2313 | hlen + tlen + sizeof(struct sockaddr_ll), |
| 2314 | 0, &err); | 2314 | !need_wait, &err); |
| 2315 | 2315 | ||
| 2316 | if (unlikely(skb == NULL)) | 2316 | if (unlikely(skb == NULL)) { |
| 2317 | /* we assume the socket was initially writeable ... */ | ||
| 2318 | if (likely(len_sum > 0)) | ||
| 2319 | err = len_sum; | ||
| 2317 | goto out_status; | 2320 | goto out_status; |
| 2318 | 2321 | } | |
| 2319 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 2322 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, |
| 2320 | addr, hlen); | 2323 | addr, hlen); |
| 2321 | if (tp_len > dev->mtu + dev->hard_header_len) { | 2324 | if (tp_len > dev->mtu + dev->hard_header_len) { |
diff --git a/net/rds/connection.c b/net/rds/connection.c index 14f041398ca1..da6da57e5f36 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c | |||
| @@ -126,7 +126,10 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
| 126 | struct rds_transport *loop_trans; | 126 | struct rds_transport *loop_trans; |
| 127 | unsigned long flags; | 127 | unsigned long flags; |
| 128 | int ret; | 128 | int ret; |
| 129 | struct rds_transport *otrans = trans; | ||
| 129 | 130 | ||
| 131 | if (!is_outgoing && otrans->t_type == RDS_TRANS_TCP) | ||
| 132 | goto new_conn; | ||
| 130 | rcu_read_lock(); | 133 | rcu_read_lock(); |
| 131 | conn = rds_conn_lookup(head, laddr, faddr, trans); | 134 | conn = rds_conn_lookup(head, laddr, faddr, trans); |
| 132 | if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport && | 135 | if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport && |
| @@ -142,6 +145,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
| 142 | if (conn) | 145 | if (conn) |
| 143 | goto out; | 146 | goto out; |
| 144 | 147 | ||
| 148 | new_conn: | ||
| 145 | conn = kmem_cache_zalloc(rds_conn_slab, gfp); | 149 | conn = kmem_cache_zalloc(rds_conn_slab, gfp); |
| 146 | if (!conn) { | 150 | if (!conn) { |
| 147 | conn = ERR_PTR(-ENOMEM); | 151 | conn = ERR_PTR(-ENOMEM); |
| @@ -230,13 +234,22 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
| 230 | /* Creating normal conn */ | 234 | /* Creating normal conn */ |
| 231 | struct rds_connection *found; | 235 | struct rds_connection *found; |
| 232 | 236 | ||
| 233 | found = rds_conn_lookup(head, laddr, faddr, trans); | 237 | if (!is_outgoing && otrans->t_type == RDS_TRANS_TCP) |
| 238 | found = NULL; | ||
| 239 | else | ||
| 240 | found = rds_conn_lookup(head, laddr, faddr, trans); | ||
| 234 | if (found) { | 241 | if (found) { |
| 235 | trans->conn_free(conn->c_transport_data); | 242 | trans->conn_free(conn->c_transport_data); |
| 236 | kmem_cache_free(rds_conn_slab, conn); | 243 | kmem_cache_free(rds_conn_slab, conn); |
| 237 | conn = found; | 244 | conn = found; |
| 238 | } else { | 245 | } else { |
| 239 | hlist_add_head_rcu(&conn->c_hash_node, head); | 246 | if ((is_outgoing && otrans->t_type == RDS_TRANS_TCP) || |
| 247 | (otrans->t_type != RDS_TRANS_TCP)) { | ||
| 248 | /* Only the active side should be added to | ||
| 249 | * reconnect list for TCP. | ||
| 250 | */ | ||
| 251 | hlist_add_head_rcu(&conn->c_hash_node, head); | ||
| 252 | } | ||
| 240 | rds_cong_add_conn(conn); | 253 | rds_cong_add_conn(conn); |
| 241 | rds_conn_count++; | 254 | rds_conn_count++; |
| 242 | } | 255 | } |
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 31b74f5e61ad..8a09ee7db3c1 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
| @@ -183,8 +183,17 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even | |||
| 183 | 183 | ||
| 184 | /* If the peer gave us the last packet it saw, process this as if | 184 | /* If the peer gave us the last packet it saw, process this as if |
| 185 | * we had received a regular ACK. */ | 185 | * we had received a regular ACK. */ |
| 186 | if (dp && dp->dp_ack_seq) | 186 | if (dp) { |
| 187 | rds_send_drop_acked(conn, be64_to_cpu(dp->dp_ack_seq), NULL); | 187 | /* dp structure start is not guaranteed to be 8 bytes aligned. |
| 188 | * Since dp_ack_seq is 64-bit extended load operations can be | ||
| 189 | * used so go through get_unaligned to avoid unaligned errors. | ||
| 190 | */ | ||
| 191 | __be64 dp_ack_seq = get_unaligned(&dp->dp_ack_seq); | ||
| 192 | |||
| 193 | if (dp_ack_seq) | ||
| 194 | rds_send_drop_acked(conn, be64_to_cpu(dp_ack_seq), | ||
| 195 | NULL); | ||
| 196 | } | ||
| 188 | 197 | ||
| 189 | rds_connect_complete(conn); | 198 | rds_connect_complete(conn); |
| 190 | } | 199 | } |
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index f9f564a6c960..973109c7b8e8 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c | |||
| @@ -62,6 +62,7 @@ void rds_tcp_state_change(struct sock *sk) | |||
| 62 | case TCP_ESTABLISHED: | 62 | case TCP_ESTABLISHED: |
| 63 | rds_connect_complete(conn); | 63 | rds_connect_complete(conn); |
| 64 | break; | 64 | break; |
| 65 | case TCP_CLOSE_WAIT: | ||
| 65 | case TCP_CLOSE: | 66 | case TCP_CLOSE: |
| 66 | rds_conn_drop(conn); | 67 | rds_conn_drop(conn); |
| 67 | default: | 68 | default: |
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 23ab4dcd1d9f..0da49e34495f 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c | |||
| @@ -45,12 +45,45 @@ static void rds_tcp_accept_worker(struct work_struct *work); | |||
| 45 | static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker); | 45 | static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker); |
| 46 | static struct socket *rds_tcp_listen_sock; | 46 | static struct socket *rds_tcp_listen_sock; |
| 47 | 47 | ||
| 48 | static int rds_tcp_keepalive(struct socket *sock) | ||
| 49 | { | ||
| 50 | /* values below based on xs_udp_default_timeout */ | ||
| 51 | int keepidle = 5; /* send a probe 'keepidle' secs after last data */ | ||
| 52 | int keepcnt = 5; /* number of unack'ed probes before declaring dead */ | ||
| 53 | int keepalive = 1; | ||
| 54 | int ret = 0; | ||
| 55 | |||
| 56 | ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, | ||
| 57 | (char *)&keepalive, sizeof(keepalive)); | ||
| 58 | if (ret < 0) | ||
| 59 | goto bail; | ||
| 60 | |||
| 61 | ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, | ||
| 62 | (char *)&keepcnt, sizeof(keepcnt)); | ||
| 63 | if (ret < 0) | ||
| 64 | goto bail; | ||
| 65 | |||
| 66 | ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, | ||
| 67 | (char *)&keepidle, sizeof(keepidle)); | ||
| 68 | if (ret < 0) | ||
| 69 | goto bail; | ||
| 70 | |||
| 71 | /* KEEPINTVL is the interval between successive probes. We follow | ||
| 72 | * the model in xs_tcp_finish_connecting() and re-use keepidle. | ||
| 73 | */ | ||
| 74 | ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, | ||
| 75 | (char *)&keepidle, sizeof(keepidle)); | ||
| 76 | bail: | ||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | |||
| 48 | static int rds_tcp_accept_one(struct socket *sock) | 80 | static int rds_tcp_accept_one(struct socket *sock) |
| 49 | { | 81 | { |
| 50 | struct socket *new_sock = NULL; | 82 | struct socket *new_sock = NULL; |
| 51 | struct rds_connection *conn; | 83 | struct rds_connection *conn; |
| 52 | int ret; | 84 | int ret; |
| 53 | struct inet_sock *inet; | 85 | struct inet_sock *inet; |
| 86 | struct rds_tcp_connection *rs_tcp; | ||
| 54 | 87 | ||
| 55 | ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, | 88 | ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, |
| 56 | sock->sk->sk_protocol, &new_sock); | 89 | sock->sk->sk_protocol, &new_sock); |
| @@ -63,6 +96,10 @@ static int rds_tcp_accept_one(struct socket *sock) | |||
| 63 | if (ret < 0) | 96 | if (ret < 0) |
| 64 | goto out; | 97 | goto out; |
| 65 | 98 | ||
| 99 | ret = rds_tcp_keepalive(new_sock); | ||
| 100 | if (ret < 0) | ||
| 101 | goto out; | ||
| 102 | |||
| 66 | rds_tcp_tune(new_sock); | 103 | rds_tcp_tune(new_sock); |
| 67 | 104 | ||
| 68 | inet = inet_sk(new_sock->sk); | 105 | inet = inet_sk(new_sock->sk); |
| @@ -77,6 +114,15 @@ static int rds_tcp_accept_one(struct socket *sock) | |||
| 77 | ret = PTR_ERR(conn); | 114 | ret = PTR_ERR(conn); |
| 78 | goto out; | 115 | goto out; |
| 79 | } | 116 | } |
| 117 | /* An incoming SYN request came in, and TCP just accepted it. | ||
| 118 | * We always create a new conn for listen side of TCP, and do not | ||
| 119 | * add it to the c_hash_list. | ||
| 120 | * | ||
| 121 | * If the client reboots, this conn will need to be cleaned up. | ||
| 122 | * rds_tcp_state_change() will do that cleanup | ||
| 123 | */ | ||
| 124 | rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data; | ||
| 125 | WARN_ON(!rs_tcp || rs_tcp->t_sock); | ||
| 80 | 126 | ||
| 81 | /* | 127 | /* |
| 82 | * see the comment above rds_queue_delayed_reconnect() | 128 | * see the comment above rds_queue_delayed_reconnect() |
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 8e472518f9f6..295d14bd6c67 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c | |||
| @@ -63,7 +63,6 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, | |||
| 63 | skb->mark = c->mark; | 63 | skb->mark = c->mark; |
| 64 | /* using overlimits stats to count how many packets marked */ | 64 | /* using overlimits stats to count how many packets marked */ |
| 65 | ca->tcf_qstats.overlimits++; | 65 | ca->tcf_qstats.overlimits++; |
| 66 | nf_ct_put(c); | ||
| 67 | goto out; | 66 | goto out; |
| 68 | } | 67 | } |
| 69 | 68 | ||
| @@ -82,7 +81,6 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, | |||
| 82 | nf_ct_put(c); | 81 | nf_ct_put(c); |
| 83 | 82 | ||
| 84 | out: | 83 | out: |
| 85 | skb->nfct = NULL; | ||
| 86 | spin_unlock(&ca->tcf_lock); | 84 | spin_unlock(&ca->tcf_lock); |
| 87 | return ca->tcf_action; | 85 | return ca->tcf_action; |
| 88 | } | 86 | } |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 8b0470e418dc..a75864d93142 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
| @@ -81,6 +81,11 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops) | |||
| 81 | struct tcf_proto_ops *t; | 81 | struct tcf_proto_ops *t; |
| 82 | int rc = -ENOENT; | 82 | int rc = -ENOENT; |
| 83 | 83 | ||
| 84 | /* Wait for outstanding call_rcu()s, if any, from a | ||
| 85 | * tcf_proto_ops's destroy() handler. | ||
| 86 | */ | ||
| 87 | rcu_barrier(); | ||
| 88 | |||
| 84 | write_lock(&cls_mod_lock); | 89 | write_lock(&cls_mod_lock); |
| 85 | list_for_each_entry(t, &tcf_proto_base, head) { | 90 | list_for_each_entry(t, &tcf_proto_base, head) { |
| 86 | if (t == ops) { | 91 | if (t == ops) { |
| @@ -308,12 +313,11 @@ replay: | |||
| 308 | case RTM_DELTFILTER: | 313 | case RTM_DELTFILTER: |
| 309 | err = tp->ops->delete(tp, fh); | 314 | err = tp->ops->delete(tp, fh); |
| 310 | if (err == 0) { | 315 | if (err == 0) { |
| 311 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); | 316 | struct tcf_proto *next = rtnl_dereference(tp->next); |
| 312 | if (tcf_destroy(tp, false)) { | ||
| 313 | struct tcf_proto *next = rtnl_dereference(tp->next); | ||
| 314 | 317 | ||
| 318 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); | ||
| 319 | if (tcf_destroy(tp, false)) | ||
| 315 | RCU_INIT_POINTER(*back, next); | 320 | RCU_INIT_POINTER(*back, next); |
| 316 | } | ||
| 317 | } | 321 | } |
| 318 | goto errout; | 322 | goto errout; |
| 319 | case RTM_GETTFILTER: | 323 | case RTM_GETTFILTER: |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index ad9eed70bc8f..1e1c89e51a11 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -815,10 +815,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
| 815 | if (dev->flags & IFF_UP) | 815 | if (dev->flags & IFF_UP) |
| 816 | dev_deactivate(dev); | 816 | dev_deactivate(dev); |
| 817 | 817 | ||
| 818 | if (new && new->ops->attach) { | 818 | if (new && new->ops->attach) |
| 819 | new->ops->attach(new); | 819 | goto skip; |
| 820 | num_q = 0; | ||
| 821 | } | ||
| 822 | 820 | ||
| 823 | for (i = 0; i < num_q; i++) { | 821 | for (i = 0; i < num_q; i++) { |
| 824 | struct netdev_queue *dev_queue = dev_ingress_queue(dev); | 822 | struct netdev_queue *dev_queue = dev_ingress_queue(dev); |
| @@ -834,12 +832,16 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
| 834 | qdisc_destroy(old); | 832 | qdisc_destroy(old); |
| 835 | } | 833 | } |
| 836 | 834 | ||
| 835 | skip: | ||
| 837 | if (!ingress) { | 836 | if (!ingress) { |
| 838 | notify_and_destroy(net, skb, n, classid, | 837 | notify_and_destroy(net, skb, n, classid, |
| 839 | dev->qdisc, new); | 838 | dev->qdisc, new); |
| 840 | if (new && !new->ops->attach) | 839 | if (new && !new->ops->attach) |
| 841 | atomic_inc(&new->refcnt); | 840 | atomic_inc(&new->refcnt); |
| 842 | dev->qdisc = new ? : &noop_qdisc; | 841 | dev->qdisc = new ? : &noop_qdisc; |
| 842 | |||
| 843 | if (new && new->ops->attach) | ||
| 844 | new->ops->attach(new); | ||
| 843 | } else { | 845 | } else { |
| 844 | notify_and_destroy(net, skb, n, classid, old, new); | 846 | notify_and_destroy(net, skb, n, classid, old, new); |
| 845 | } | 847 | } |
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index de28f8e968e8..7a0bdb16ac92 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c | |||
| @@ -164,7 +164,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt) | |||
| 164 | 164 | ||
| 165 | sch->limit = DEFAULT_CODEL_LIMIT; | 165 | sch->limit = DEFAULT_CODEL_LIMIT; |
| 166 | 166 | ||
| 167 | codel_params_init(&q->params); | 167 | codel_params_init(&q->params, sch); |
| 168 | codel_vars_init(&q->vars); | 168 | codel_vars_init(&q->vars); |
| 169 | codel_stats_init(&q->stats); | 169 | codel_stats_init(&q->stats); |
| 170 | 170 | ||
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 1e52decb7b59..c244c45b78d7 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
| @@ -391,7 +391,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) | |||
| 391 | q->perturbation = prandom_u32(); | 391 | q->perturbation = prandom_u32(); |
| 392 | INIT_LIST_HEAD(&q->new_flows); | 392 | INIT_LIST_HEAD(&q->new_flows); |
| 393 | INIT_LIST_HEAD(&q->old_flows); | 393 | INIT_LIST_HEAD(&q->old_flows); |
| 394 | codel_params_init(&q->cparams); | 394 | codel_params_init(&q->cparams, sch); |
| 395 | codel_stats_init(&q->cstats); | 395 | codel_stats_init(&q->cstats); |
| 396 | q->cparams.ecn = true; | 396 | q->cparams.ecn = true; |
| 397 | 397 | ||
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index a4ca4517cdc8..634529e0ce6b 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c | |||
| @@ -229,7 +229,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
| 229 | break; | 229 | break; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | if (q->backlog + qdisc_pkt_len(skb) <= q->limit) { | 232 | if (gred_backlog(t, q, sch) + qdisc_pkt_len(skb) <= q->limit) { |
| 233 | q->backlog += qdisc_pkt_len(skb); | 233 | q->backlog += qdisc_pkt_len(skb); |
| 234 | return qdisc_enqueue_tail(skb, sch); | 234 | return qdisc_enqueue_tail(skb, sch); |
| 235 | } | 235 | } |
| @@ -553,7 +553,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 553 | 553 | ||
| 554 | opt.limit = q->limit; | 554 | opt.limit = q->limit; |
| 555 | opt.DP = q->DP; | 555 | opt.DP = q->DP; |
| 556 | opt.backlog = q->backlog; | 556 | opt.backlog = gred_backlog(table, q, sch); |
| 557 | opt.prio = q->prio; | 557 | opt.prio = q->prio; |
| 558 | opt.qth_min = q->parms.qth_min >> q->parms.Wlog; | 558 | opt.qth_min = q->parms.qth_min >> q->parms.Wlog; |
| 559 | opt.qth_max = q->parms.qth_max >> q->parms.Wlog; | 559 | opt.qth_max = q->parms.qth_max >> q->parms.Wlog; |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index fb7976aee61c..4f15b7d730e1 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
| @@ -381,13 +381,14 @@ nomem: | |||
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | 383 | ||
| 384 | /* Public interface to creat the association shared key. | 384 | /* Public interface to create the association shared key. |
| 385 | * See code above for the algorithm. | 385 | * See code above for the algorithm. |
| 386 | */ | 386 | */ |
| 387 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) | 387 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) |
| 388 | { | 388 | { |
| 389 | struct sctp_auth_bytes *secret; | 389 | struct sctp_auth_bytes *secret; |
| 390 | struct sctp_shared_key *ep_key; | 390 | struct sctp_shared_key *ep_key; |
| 391 | struct sctp_chunk *chunk; | ||
| 391 | 392 | ||
| 392 | /* If we don't support AUTH, or peer is not capable | 393 | /* If we don't support AUTH, or peer is not capable |
| 393 | * we don't need to do anything. | 394 | * we don't need to do anything. |
| @@ -410,6 +411,14 @@ int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) | |||
| 410 | sctp_auth_key_put(asoc->asoc_shared_key); | 411 | sctp_auth_key_put(asoc->asoc_shared_key); |
| 411 | asoc->asoc_shared_key = secret; | 412 | asoc->asoc_shared_key = secret; |
| 412 | 413 | ||
| 414 | /* Update send queue in case any chunk already in there now | ||
| 415 | * needs authenticating | ||
| 416 | */ | ||
| 417 | list_for_each_entry(chunk, &asoc->outqueue.out_chunk_list, list) { | ||
| 418 | if (sctp_auth_send_cid(chunk->chunk_hdr->type, asoc)) | ||
| 419 | chunk->auth = 1; | ||
| 420 | } | ||
| 421 | |||
| 413 | return 0; | 422 | return 0; |
| 414 | } | 423 | } |
| 415 | 424 | ||
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 1ec19f6f0c2b..eeeba5adee6d 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
| @@ -793,20 +793,26 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
| 793 | { | 793 | { |
| 794 | u32 value_follows; | 794 | u32 value_follows; |
| 795 | int err; | 795 | int err; |
| 796 | struct page *scratch; | ||
| 797 | |||
| 798 | scratch = alloc_page(GFP_KERNEL); | ||
| 799 | if (!scratch) | ||
| 800 | return -ENOMEM; | ||
| 801 | xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); | ||
| 796 | 802 | ||
| 797 | /* res->status */ | 803 | /* res->status */ |
| 798 | err = gssx_dec_status(xdr, &res->status); | 804 | err = gssx_dec_status(xdr, &res->status); |
| 799 | if (err) | 805 | if (err) |
| 800 | return err; | 806 | goto out_free; |
| 801 | 807 | ||
| 802 | /* res->context_handle */ | 808 | /* res->context_handle */ |
| 803 | err = gssx_dec_bool(xdr, &value_follows); | 809 | err = gssx_dec_bool(xdr, &value_follows); |
| 804 | if (err) | 810 | if (err) |
| 805 | return err; | 811 | goto out_free; |
| 806 | if (value_follows) { | 812 | if (value_follows) { |
| 807 | err = gssx_dec_ctx(xdr, res->context_handle); | 813 | err = gssx_dec_ctx(xdr, res->context_handle); |
| 808 | if (err) | 814 | if (err) |
| 809 | return err; | 815 | goto out_free; |
| 810 | } else { | 816 | } else { |
| 811 | res->context_handle = NULL; | 817 | res->context_handle = NULL; |
| 812 | } | 818 | } |
| @@ -814,11 +820,11 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
| 814 | /* res->output_token */ | 820 | /* res->output_token */ |
| 815 | err = gssx_dec_bool(xdr, &value_follows); | 821 | err = gssx_dec_bool(xdr, &value_follows); |
| 816 | if (err) | 822 | if (err) |
| 817 | return err; | 823 | goto out_free; |
| 818 | if (value_follows) { | 824 | if (value_follows) { |
| 819 | err = gssx_dec_buffer(xdr, res->output_token); | 825 | err = gssx_dec_buffer(xdr, res->output_token); |
| 820 | if (err) | 826 | if (err) |
| 821 | return err; | 827 | goto out_free; |
| 822 | } else { | 828 | } else { |
| 823 | res->output_token = NULL; | 829 | res->output_token = NULL; |
| 824 | } | 830 | } |
| @@ -826,14 +832,17 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
| 826 | /* res->delegated_cred_handle */ | 832 | /* res->delegated_cred_handle */ |
| 827 | err = gssx_dec_bool(xdr, &value_follows); | 833 | err = gssx_dec_bool(xdr, &value_follows); |
| 828 | if (err) | 834 | if (err) |
| 829 | return err; | 835 | goto out_free; |
| 830 | if (value_follows) { | 836 | if (value_follows) { |
| 831 | /* we do not support upcall servers sending this data. */ | 837 | /* we do not support upcall servers sending this data. */ |
| 832 | return -EINVAL; | 838 | err = -EINVAL; |
| 839 | goto out_free; | ||
| 833 | } | 840 | } |
| 834 | 841 | ||
| 835 | /* res->options */ | 842 | /* res->options */ |
| 836 | err = gssx_dec_option_array(xdr, &res->options); | 843 | err = gssx_dec_option_array(xdr, &res->options); |
| 837 | 844 | ||
| 845 | out_free: | ||
| 846 | __free_page(scratch); | ||
| 838 | return err; | 847 | return err; |
| 839 | } | 848 | } |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 46568b85c333..055453d48668 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
| @@ -338,7 +338,7 @@ int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, | |||
| 338 | fi, tos, type, nlflags, | 338 | fi, tos, type, nlflags, |
| 339 | tb_id); | 339 | tb_id); |
| 340 | if (!err) | 340 | if (!err) |
| 341 | fi->fib_flags |= RTNH_F_EXTERNAL; | 341 | fi->fib_flags |= RTNH_F_OFFLOAD; |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | return err; | 344 | return err; |
| @@ -364,7 +364,7 @@ int netdev_switch_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | |||
| 364 | const struct swdev_ops *ops; | 364 | const struct swdev_ops *ops; |
| 365 | int err = 0; | 365 | int err = 0; |
| 366 | 366 | ||
| 367 | if (!(fi->fib_flags & RTNH_F_EXTERNAL)) | 367 | if (!(fi->fib_flags & RTNH_F_OFFLOAD)) |
| 368 | return 0; | 368 | return 0; |
| 369 | 369 | ||
| 370 | dev = netdev_switch_get_dev_by_nhs(fi); | 370 | dev = netdev_switch_get_dev_by_nhs(fi); |
| @@ -376,7 +376,7 @@ int netdev_switch_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, | |||
| 376 | err = ops->swdev_fib_ipv4_del(dev, htonl(dst), dst_len, | 376 | err = ops->swdev_fib_ipv4_del(dev, htonl(dst), dst_len, |
| 377 | fi, tos, type, tb_id); | 377 | fi, tos, type, tb_id); |
| 378 | if (!err) | 378 | if (!err) |
| 379 | fi->fib_flags &= ~RTNH_F_EXTERNAL; | 379 | fi->fib_flags &= ~RTNH_F_OFFLOAD; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | return err; | 382 | return err; |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 3613e72e858e..70e3dacbf84a 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -591,14 +591,14 @@ void tipc_bearer_stop(struct net *net) | |||
| 591 | 591 | ||
| 592 | /* Caller should hold rtnl_lock to protect the bearer */ | 592 | /* Caller should hold rtnl_lock to protect the bearer */ |
| 593 | static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, | 593 | static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, |
| 594 | struct tipc_bearer *bearer) | 594 | struct tipc_bearer *bearer, int nlflags) |
| 595 | { | 595 | { |
| 596 | void *hdr; | 596 | void *hdr; |
| 597 | struct nlattr *attrs; | 597 | struct nlattr *attrs; |
| 598 | struct nlattr *prop; | 598 | struct nlattr *prop; |
| 599 | 599 | ||
| 600 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | 600 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, |
| 601 | NLM_F_MULTI, TIPC_NL_BEARER_GET); | 601 | nlflags, TIPC_NL_BEARER_GET); |
| 602 | if (!hdr) | 602 | if (!hdr) |
| 603 | return -EMSGSIZE; | 603 | return -EMSGSIZE; |
| 604 | 604 | ||
| @@ -657,7 +657,7 @@ int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 657 | if (!bearer) | 657 | if (!bearer) |
| 658 | continue; | 658 | continue; |
| 659 | 659 | ||
| 660 | err = __tipc_nl_add_bearer(&msg, bearer); | 660 | err = __tipc_nl_add_bearer(&msg, bearer, NLM_F_MULTI); |
| 661 | if (err) | 661 | if (err) |
| 662 | break; | 662 | break; |
| 663 | } | 663 | } |
| @@ -705,7 +705,7 @@ int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info) | |||
| 705 | goto err_out; | 705 | goto err_out; |
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | err = __tipc_nl_add_bearer(&msg, bearer); | 708 | err = __tipc_nl_add_bearer(&msg, bearer, 0); |
| 709 | if (err) | 709 | if (err) |
| 710 | goto err_out; | 710 | goto err_out; |
| 711 | rtnl_unlock(); | 711 | rtnl_unlock(); |
| @@ -857,14 +857,14 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) | |||
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | static int __tipc_nl_add_media(struct tipc_nl_msg *msg, | 859 | static int __tipc_nl_add_media(struct tipc_nl_msg *msg, |
| 860 | struct tipc_media *media) | 860 | struct tipc_media *media, int nlflags) |
| 861 | { | 861 | { |
| 862 | void *hdr; | 862 | void *hdr; |
| 863 | struct nlattr *attrs; | 863 | struct nlattr *attrs; |
| 864 | struct nlattr *prop; | 864 | struct nlattr *prop; |
| 865 | 865 | ||
| 866 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | 866 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, |
| 867 | NLM_F_MULTI, TIPC_NL_MEDIA_GET); | 867 | nlflags, TIPC_NL_MEDIA_GET); |
| 868 | if (!hdr) | 868 | if (!hdr) |
| 869 | return -EMSGSIZE; | 869 | return -EMSGSIZE; |
| 870 | 870 | ||
| @@ -916,7 +916,8 @@ int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 916 | 916 | ||
| 917 | rtnl_lock(); | 917 | rtnl_lock(); |
| 918 | for (; media_info_array[i] != NULL; i++) { | 918 | for (; media_info_array[i] != NULL; i++) { |
| 919 | err = __tipc_nl_add_media(&msg, media_info_array[i]); | 919 | err = __tipc_nl_add_media(&msg, media_info_array[i], |
| 920 | NLM_F_MULTI); | ||
| 920 | if (err) | 921 | if (err) |
| 921 | break; | 922 | break; |
| 922 | } | 923 | } |
| @@ -963,7 +964,7 @@ int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info) | |||
| 963 | goto err_out; | 964 | goto err_out; |
| 964 | } | 965 | } |
| 965 | 966 | ||
| 966 | err = __tipc_nl_add_media(&msg, media); | 967 | err = __tipc_nl_add_media(&msg, media, 0); |
| 967 | if (err) | 968 | if (err) |
| 968 | goto err_out; | 969 | goto err_out; |
| 969 | rtnl_unlock(); | 970 | rtnl_unlock(); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index a6b30df6ec02..43a515dc97b0 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -1145,11 +1145,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) | |||
| 1145 | } | 1145 | } |
| 1146 | /* Synchronize with parallel link if applicable */ | 1146 | /* Synchronize with parallel link if applicable */ |
| 1147 | if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) { | 1147 | if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) { |
| 1148 | link_handle_out_of_seq_msg(l_ptr, skb); | 1148 | if (!link_synch(l_ptr)) |
| 1149 | if (link_synch(l_ptr)) | 1149 | goto unlock; |
| 1150 | link_retrieve_defq(l_ptr, &head); | ||
| 1151 | skb = NULL; | ||
| 1152 | goto unlock; | ||
| 1153 | } | 1150 | } |
| 1154 | l_ptr->next_in_no++; | 1151 | l_ptr->next_in_no++; |
| 1155 | if (unlikely(!skb_queue_empty(&l_ptr->deferdq))) | 1152 | if (unlikely(!skb_queue_empty(&l_ptr->deferdq))) |
| @@ -2013,7 +2010,7 @@ msg_full: | |||
| 2013 | 2010 | ||
| 2014 | /* Caller should hold appropriate locks to protect the link */ | 2011 | /* Caller should hold appropriate locks to protect the link */ |
| 2015 | static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | 2012 | static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, |
| 2016 | struct tipc_link *link) | 2013 | struct tipc_link *link, int nlflags) |
| 2017 | { | 2014 | { |
| 2018 | int err; | 2015 | int err; |
| 2019 | void *hdr; | 2016 | void *hdr; |
| @@ -2022,7 +2019,7 @@ static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | |||
| 2022 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 2019 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 2023 | 2020 | ||
| 2024 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | 2021 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, |
| 2025 | NLM_F_MULTI, TIPC_NL_LINK_GET); | 2022 | nlflags, TIPC_NL_LINK_GET); |
| 2026 | if (!hdr) | 2023 | if (!hdr) |
| 2027 | return -EMSGSIZE; | 2024 | return -EMSGSIZE; |
| 2028 | 2025 | ||
| @@ -2095,7 +2092,7 @@ static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, | |||
| 2095 | if (!node->links[i]) | 2092 | if (!node->links[i]) |
| 2096 | continue; | 2093 | continue; |
| 2097 | 2094 | ||
| 2098 | err = __tipc_nl_add_link(net, msg, node->links[i]); | 2095 | err = __tipc_nl_add_link(net, msg, node->links[i], NLM_F_MULTI); |
| 2099 | if (err) | 2096 | if (err) |
| 2100 | return err; | 2097 | return err; |
| 2101 | } | 2098 | } |
| @@ -2143,7 +2140,6 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2143 | err = __tipc_nl_add_node_links(net, &msg, node, | 2140 | err = __tipc_nl_add_node_links(net, &msg, node, |
| 2144 | &prev_link); | 2141 | &prev_link); |
| 2145 | tipc_node_unlock(node); | 2142 | tipc_node_unlock(node); |
| 2146 | tipc_node_put(node); | ||
| 2147 | if (err) | 2143 | if (err) |
| 2148 | goto out; | 2144 | goto out; |
| 2149 | 2145 | ||
| @@ -2210,7 +2206,7 @@ int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info) | |||
| 2210 | goto err_out; | 2206 | goto err_out; |
| 2211 | } | 2207 | } |
| 2212 | 2208 | ||
| 2213 | err = __tipc_nl_add_link(net, &msg, link); | 2209 | err = __tipc_nl_add_link(net, &msg, link, 0); |
| 2214 | if (err) | 2210 | if (err) |
| 2215 | goto err_out; | 2211 | goto err_out; |
| 2216 | 2212 | ||
diff --git a/net/tipc/server.c b/net/tipc/server.c index ab6183cdb121..77ff03ed1e18 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
| @@ -102,7 +102,7 @@ static void tipc_conn_kref_release(struct kref *kref) | |||
| 102 | } | 102 | } |
| 103 | saddr->scope = -TIPC_NODE_SCOPE; | 103 | saddr->scope = -TIPC_NODE_SCOPE; |
| 104 | kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); | 104 | kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); |
| 105 | sk_release_kernel(sk); | 105 | sock_release(sock); |
| 106 | con->sock = NULL; | 106 | con->sock = NULL; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| @@ -321,12 +321,9 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) | |||
| 321 | struct socket *sock = NULL; | 321 | struct socket *sock = NULL; |
| 322 | int ret; | 322 | int ret; |
| 323 | 323 | ||
| 324 | ret = sock_create_kern(AF_TIPC, SOCK_SEQPACKET, 0, &sock); | 324 | ret = __sock_create(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock, 1); |
| 325 | if (ret < 0) | 325 | if (ret < 0) |
| 326 | return NULL; | 326 | return NULL; |
| 327 | |||
| 328 | sk_change_net(sock->sk, s->net); | ||
| 329 | |||
| 330 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, | 327 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, |
| 331 | (char *)&s->imp, sizeof(s->imp)); | 328 | (char *)&s->imp, sizeof(s->imp)); |
| 332 | if (ret < 0) | 329 | if (ret < 0) |
| @@ -376,7 +373,7 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) | |||
| 376 | 373 | ||
| 377 | create_err: | 374 | create_err: |
| 378 | kernel_sock_shutdown(sock, SHUT_RDWR); | 375 | kernel_sock_shutdown(sock, SHUT_RDWR); |
| 379 | sk_release_kernel(sock->sk); | 376 | sock_release(sock); |
| 380 | return NULL; | 377 | return NULL; |
| 381 | } | 378 | } |
| 382 | 379 | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index ee90d74d7516..f485600c4507 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -1764,13 +1764,14 @@ static int tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, | |||
| 1764 | int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) | 1764 | int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) |
| 1765 | { | 1765 | { |
| 1766 | u32 dnode, dport = 0; | 1766 | u32 dnode, dport = 0; |
| 1767 | int err = -TIPC_ERR_NO_PORT; | 1767 | int err; |
| 1768 | struct sk_buff *skb; | 1768 | struct sk_buff *skb; |
| 1769 | struct tipc_sock *tsk; | 1769 | struct tipc_sock *tsk; |
| 1770 | struct tipc_net *tn; | 1770 | struct tipc_net *tn; |
| 1771 | struct sock *sk; | 1771 | struct sock *sk; |
| 1772 | 1772 | ||
| 1773 | while (skb_queue_len(inputq)) { | 1773 | while (skb_queue_len(inputq)) { |
| 1774 | err = -TIPC_ERR_NO_PORT; | ||
| 1774 | skb = NULL; | 1775 | skb = NULL; |
| 1775 | dport = tipc_skb_peek_port(inputq, dport); | 1776 | dport = tipc_skb_peek_port(inputq, dport); |
| 1776 | tsk = tipc_sk_lookup(net, dport); | 1777 | tsk = tipc_sk_lookup(net, dport); |
| @@ -2141,11 +2142,17 @@ static void tipc_sk_timeout(unsigned long data) | |||
| 2141 | peer_node = tsk_peer_node(tsk); | 2142 | peer_node = tsk_peer_node(tsk); |
| 2142 | 2143 | ||
| 2143 | if (tsk->probing_state == TIPC_CONN_PROBING) { | 2144 | if (tsk->probing_state == TIPC_CONN_PROBING) { |
| 2144 | /* Previous probe not answered -> self abort */ | 2145 | if (!sock_owned_by_user(sk)) { |
| 2145 | skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, | 2146 | sk->sk_socket->state = SS_DISCONNECTING; |
| 2146 | TIPC_CONN_MSG, SHORT_H_SIZE, 0, | 2147 | tsk->connected = 0; |
| 2147 | own_node, peer_node, tsk->portid, | 2148 | tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk), |
| 2148 | peer_port, TIPC_ERR_NO_PORT); | 2149 | tsk_peer_port(tsk)); |
| 2150 | sk->sk_state_change(sk); | ||
| 2151 | } else { | ||
| 2152 | /* Try again later */ | ||
| 2153 | sk_reset_timer(sk, &sk->sk_timer, (HZ / 20)); | ||
| 2154 | } | ||
| 2155 | |||
| 2149 | } else { | 2156 | } else { |
| 2150 | skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, | 2157 | skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, |
| 2151 | INT_H_SIZE, 0, peer_node, own_node, | 2158 | INT_H_SIZE, 0, peer_node, own_node, |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 5266ea7b922b..06430598cf51 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -1880,6 +1880,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, | |||
| 1880 | unix_state_unlock(sk); | 1880 | unix_state_unlock(sk); |
| 1881 | timeo = freezable_schedule_timeout(timeo); | 1881 | timeo = freezable_schedule_timeout(timeo); |
| 1882 | unix_state_lock(sk); | 1882 | unix_state_lock(sk); |
| 1883 | |||
| 1884 | if (sock_flag(sk, SOCK_DEAD)) | ||
| 1885 | break; | ||
| 1886 | |||
| 1883 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1887 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 1884 | } | 1888 | } |
| 1885 | 1889 | ||
| @@ -1939,6 +1943,10 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, | |||
| 1939 | struct sk_buff *skb, *last; | 1943 | struct sk_buff *skb, *last; |
| 1940 | 1944 | ||
| 1941 | unix_state_lock(sk); | 1945 | unix_state_lock(sk); |
| 1946 | if (sock_flag(sk, SOCK_DEAD)) { | ||
| 1947 | err = -ECONNRESET; | ||
| 1948 | goto unlock; | ||
| 1949 | } | ||
| 1942 | last = skb = skb_peek(&sk->sk_receive_queue); | 1950 | last = skb = skb_peek(&sk->sk_receive_queue); |
| 1943 | again: | 1951 | again: |
| 1944 | if (skb == NULL) { | 1952 | if (skb == NULL) { |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 99f7012b23b9..a73a226f2d33 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
| @@ -95,39 +95,36 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait); | |||
| 95 | 95 | ||
| 96 | unsigned int unix_tot_inflight; | 96 | unsigned int unix_tot_inflight; |
| 97 | 97 | ||
| 98 | |||
| 99 | struct sock *unix_get_socket(struct file *filp) | 98 | struct sock *unix_get_socket(struct file *filp) |
| 100 | { | 99 | { |
| 101 | struct sock *u_sock = NULL; | 100 | struct sock *u_sock = NULL; |
| 102 | struct inode *inode = file_inode(filp); | 101 | struct inode *inode = file_inode(filp); |
| 103 | 102 | ||
| 104 | /* | 103 | /* Socket ? */ |
| 105 | * Socket ? | ||
| 106 | */ | ||
| 107 | if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) { | 104 | if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) { |
| 108 | struct socket *sock = SOCKET_I(inode); | 105 | struct socket *sock = SOCKET_I(inode); |
| 109 | struct sock *s = sock->sk; | 106 | struct sock *s = sock->sk; |
| 110 | 107 | ||
| 111 | /* | 108 | /* PF_UNIX ? */ |
| 112 | * PF_UNIX ? | ||
| 113 | */ | ||
| 114 | if (s && sock->ops && sock->ops->family == PF_UNIX) | 109 | if (s && sock->ops && sock->ops->family == PF_UNIX) |
| 115 | u_sock = s; | 110 | u_sock = s; |
| 116 | } | 111 | } |
| 117 | return u_sock; | 112 | return u_sock; |
| 118 | } | 113 | } |
| 119 | 114 | ||
| 120 | /* | 115 | /* Keep the number of times in flight count for the file |
| 121 | * Keep the number of times in flight count for the file | 116 | * descriptor if it is for an AF_UNIX socket. |
| 122 | * descriptor if it is for an AF_UNIX socket. | ||
| 123 | */ | 117 | */ |
| 124 | 118 | ||
| 125 | void unix_inflight(struct file *fp) | 119 | void unix_inflight(struct file *fp) |
| 126 | { | 120 | { |
| 127 | struct sock *s = unix_get_socket(fp); | 121 | struct sock *s = unix_get_socket(fp); |
| 122 | |||
| 128 | if (s) { | 123 | if (s) { |
| 129 | struct unix_sock *u = unix_sk(s); | 124 | struct unix_sock *u = unix_sk(s); |
| 125 | |||
| 130 | spin_lock(&unix_gc_lock); | 126 | spin_lock(&unix_gc_lock); |
| 127 | |||
| 131 | if (atomic_long_inc_return(&u->inflight) == 1) { | 128 | if (atomic_long_inc_return(&u->inflight) == 1) { |
| 132 | BUG_ON(!list_empty(&u->link)); | 129 | BUG_ON(!list_empty(&u->link)); |
| 133 | list_add_tail(&u->link, &gc_inflight_list); | 130 | list_add_tail(&u->link, &gc_inflight_list); |
| @@ -142,10 +139,13 @@ void unix_inflight(struct file *fp) | |||
| 142 | void unix_notinflight(struct file *fp) | 139 | void unix_notinflight(struct file *fp) |
| 143 | { | 140 | { |
| 144 | struct sock *s = unix_get_socket(fp); | 141 | struct sock *s = unix_get_socket(fp); |
| 142 | |||
| 145 | if (s) { | 143 | if (s) { |
| 146 | struct unix_sock *u = unix_sk(s); | 144 | struct unix_sock *u = unix_sk(s); |
| 145 | |||
| 147 | spin_lock(&unix_gc_lock); | 146 | spin_lock(&unix_gc_lock); |
| 148 | BUG_ON(list_empty(&u->link)); | 147 | BUG_ON(list_empty(&u->link)); |
| 148 | |||
| 149 | if (atomic_long_dec_and_test(&u->inflight)) | 149 | if (atomic_long_dec_and_test(&u->inflight)) |
| 150 | list_del_init(&u->link); | 150 | list_del_init(&u->link); |
| 151 | unix_tot_inflight--; | 151 | unix_tot_inflight--; |
| @@ -161,32 +161,27 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | |||
| 161 | 161 | ||
| 162 | spin_lock(&x->sk_receive_queue.lock); | 162 | spin_lock(&x->sk_receive_queue.lock); |
| 163 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { | 163 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { |
| 164 | /* | 164 | /* Do we have file descriptors ? */ |
| 165 | * Do we have file descriptors ? | ||
| 166 | */ | ||
| 167 | if (UNIXCB(skb).fp) { | 165 | if (UNIXCB(skb).fp) { |
| 168 | bool hit = false; | 166 | bool hit = false; |
| 169 | /* | 167 | /* Process the descriptors of this socket */ |
| 170 | * Process the descriptors of this socket | ||
| 171 | */ | ||
| 172 | int nfd = UNIXCB(skb).fp->count; | 168 | int nfd = UNIXCB(skb).fp->count; |
| 173 | struct file **fp = UNIXCB(skb).fp->fp; | 169 | struct file **fp = UNIXCB(skb).fp->fp; |
| 170 | |||
| 174 | while (nfd--) { | 171 | while (nfd--) { |
| 175 | /* | 172 | /* Get the socket the fd matches if it indeed does so */ |
| 176 | * Get the socket the fd matches | ||
| 177 | * if it indeed does so | ||
| 178 | */ | ||
| 179 | struct sock *sk = unix_get_socket(*fp++); | 173 | struct sock *sk = unix_get_socket(*fp++); |
| 174 | |||
| 180 | if (sk) { | 175 | if (sk) { |
| 181 | struct unix_sock *u = unix_sk(sk); | 176 | struct unix_sock *u = unix_sk(sk); |
| 182 | 177 | ||
| 183 | /* | 178 | /* Ignore non-candidates, they could |
| 184 | * Ignore non-candidates, they could | ||
| 185 | * have been added to the queues after | 179 | * have been added to the queues after |
| 186 | * starting the garbage collection | 180 | * starting the garbage collection |
| 187 | */ | 181 | */ |
| 188 | if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) { | 182 | if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) { |
| 189 | hit = true; | 183 | hit = true; |
| 184 | |||
| 190 | func(u); | 185 | func(u); |
| 191 | } | 186 | } |
| 192 | } | 187 | } |
| @@ -203,24 +198,22 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | |||
| 203 | static void scan_children(struct sock *x, void (*func)(struct unix_sock *), | 198 | static void scan_children(struct sock *x, void (*func)(struct unix_sock *), |
| 204 | struct sk_buff_head *hitlist) | 199 | struct sk_buff_head *hitlist) |
| 205 | { | 200 | { |
| 206 | if (x->sk_state != TCP_LISTEN) | 201 | if (x->sk_state != TCP_LISTEN) { |
| 207 | scan_inflight(x, func, hitlist); | 202 | scan_inflight(x, func, hitlist); |
| 208 | else { | 203 | } else { |
| 209 | struct sk_buff *skb; | 204 | struct sk_buff *skb; |
| 210 | struct sk_buff *next; | 205 | struct sk_buff *next; |
| 211 | struct unix_sock *u; | 206 | struct unix_sock *u; |
| 212 | LIST_HEAD(embryos); | 207 | LIST_HEAD(embryos); |
| 213 | 208 | ||
| 214 | /* | 209 | /* For a listening socket collect the queued embryos |
| 215 | * For a listening socket collect the queued embryos | ||
| 216 | * and perform a scan on them as well. | 210 | * and perform a scan on them as well. |
| 217 | */ | 211 | */ |
| 218 | spin_lock(&x->sk_receive_queue.lock); | 212 | spin_lock(&x->sk_receive_queue.lock); |
| 219 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { | 213 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { |
| 220 | u = unix_sk(skb->sk); | 214 | u = unix_sk(skb->sk); |
| 221 | 215 | ||
| 222 | /* | 216 | /* An embryo cannot be in-flight, so it's safe |
| 223 | * An embryo cannot be in-flight, so it's safe | ||
| 224 | * to use the list link. | 217 | * to use the list link. |
| 225 | */ | 218 | */ |
| 226 | BUG_ON(!list_empty(&u->link)); | 219 | BUG_ON(!list_empty(&u->link)); |
| @@ -249,8 +242,7 @@ static void inc_inflight(struct unix_sock *usk) | |||
| 249 | static void inc_inflight_move_tail(struct unix_sock *u) | 242 | static void inc_inflight_move_tail(struct unix_sock *u) |
| 250 | { | 243 | { |
| 251 | atomic_long_inc(&u->inflight); | 244 | atomic_long_inc(&u->inflight); |
| 252 | /* | 245 | /* If this still might be part of a cycle, move it to the end |
| 253 | * If this still might be part of a cycle, move it to the end | ||
| 254 | * of the list, so that it's checked even if it was already | 246 | * of the list, so that it's checked even if it was already |
| 255 | * passed over | 247 | * passed over |
| 256 | */ | 248 | */ |
| @@ -263,8 +255,7 @@ static bool gc_in_progress; | |||
| 263 | 255 | ||
| 264 | void wait_for_unix_gc(void) | 256 | void wait_for_unix_gc(void) |
| 265 | { | 257 | { |
| 266 | /* | 258 | /* If number of inflight sockets is insane, |
| 267 | * If number of inflight sockets is insane, | ||
| 268 | * force a garbage collect right now. | 259 | * force a garbage collect right now. |
| 269 | */ | 260 | */ |
| 270 | if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress) | 261 | if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress) |
| @@ -288,8 +279,7 @@ void unix_gc(void) | |||
| 288 | goto out; | 279 | goto out; |
| 289 | 280 | ||
| 290 | gc_in_progress = true; | 281 | gc_in_progress = true; |
| 291 | /* | 282 | /* First, select candidates for garbage collection. Only |
| 292 | * First, select candidates for garbage collection. Only | ||
| 293 | * in-flight sockets are considered, and from those only ones | 283 | * in-flight sockets are considered, and from those only ones |
| 294 | * which don't have any external reference. | 284 | * which don't have any external reference. |
| 295 | * | 285 | * |
| @@ -320,15 +310,13 @@ void unix_gc(void) | |||
| 320 | } | 310 | } |
| 321 | } | 311 | } |
| 322 | 312 | ||
| 323 | /* | 313 | /* Now remove all internal in-flight reference to children of |
| 324 | * Now remove all internal in-flight reference to children of | ||
| 325 | * the candidates. | 314 | * the candidates. |
| 326 | */ | 315 | */ |
| 327 | list_for_each_entry(u, &gc_candidates, link) | 316 | list_for_each_entry(u, &gc_candidates, link) |
| 328 | scan_children(&u->sk, dec_inflight, NULL); | 317 | scan_children(&u->sk, dec_inflight, NULL); |
| 329 | 318 | ||
| 330 | /* | 319 | /* Restore the references for children of all candidates, |
| 331 | * Restore the references for children of all candidates, | ||
| 332 | * which have remaining references. Do this recursively, so | 320 | * which have remaining references. Do this recursively, so |
| 333 | * only those remain, which form cyclic references. | 321 | * only those remain, which form cyclic references. |
| 334 | * | 322 | * |
| @@ -350,8 +338,7 @@ void unix_gc(void) | |||
| 350 | } | 338 | } |
| 351 | list_del(&cursor); | 339 | list_del(&cursor); |
| 352 | 340 | ||
| 353 | /* | 341 | /* not_cycle_list contains those sockets which do not make up a |
| 354 | * not_cycle_list contains those sockets which do not make up a | ||
| 355 | * cycle. Restore these to the inflight list. | 342 | * cycle. Restore these to the inflight list. |
| 356 | */ | 343 | */ |
| 357 | while (!list_empty(¬_cycle_list)) { | 344 | while (!list_empty(¬_cycle_list)) { |
| @@ -360,8 +347,7 @@ void unix_gc(void) | |||
| 360 | list_move_tail(&u->link, &gc_inflight_list); | 347 | list_move_tail(&u->link, &gc_inflight_list); |
| 361 | } | 348 | } |
| 362 | 349 | ||
| 363 | /* | 350 | /* Now gc_candidates contains only garbage. Restore original |
| 364 | * Now gc_candidates contains only garbage. Restore original | ||
| 365 | * inflight counters for these as well, and remove the skbuffs | 351 | * inflight counters for these as well, and remove the skbuffs |
| 366 | * which are creating the cycle(s). | 352 | * which are creating the cycle(s). |
| 367 | */ | 353 | */ |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index fff1bef6ed6d..fd682832a0e3 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
| @@ -1333,6 +1333,8 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
| 1333 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); | 1333 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); |
| 1334 | wdev_unlock(wdev); | 1334 | wdev_unlock(wdev); |
| 1335 | 1335 | ||
| 1336 | memset(&sinfo, 0, sizeof(sinfo)); | ||
| 1337 | |||
| 1336 | if (rdev_get_station(rdev, dev, bssid, &sinfo)) | 1338 | if (rdev_get_station(rdev, dev, bssid, &sinfo)) |
| 1337 | return NULL; | 1339 | return NULL; |
| 1338 | 1340 | ||
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 526c4feb3b50..b58286ecd156 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #include <net/dst.h> | 13 | #include <net/dst.h> |
| 14 | #include <net/ip.h> | 14 | #include <net/ip.h> |
| 15 | #include <net/xfrm.h> | 15 | #include <net/xfrm.h> |
| 16 | #include <net/ip_tunnels.h> | ||
| 17 | #include <net/ip6_tunnel.h> | ||
| 16 | 18 | ||
| 17 | static struct kmem_cache *secpath_cachep __read_mostly; | 19 | static struct kmem_cache *secpath_cachep __read_mostly; |
| 18 | 20 | ||
| @@ -186,6 +188,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 186 | struct xfrm_state *x = NULL; | 188 | struct xfrm_state *x = NULL; |
| 187 | xfrm_address_t *daddr; | 189 | xfrm_address_t *daddr; |
| 188 | struct xfrm_mode *inner_mode; | 190 | struct xfrm_mode *inner_mode; |
| 191 | u32 mark = skb->mark; | ||
| 189 | unsigned int family; | 192 | unsigned int family; |
| 190 | int decaps = 0; | 193 | int decaps = 0; |
| 191 | int async = 0; | 194 | int async = 0; |
| @@ -203,6 +206,18 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 203 | XFRM_SPI_SKB_CB(skb)->daddroff); | 206 | XFRM_SPI_SKB_CB(skb)->daddroff); |
| 204 | family = XFRM_SPI_SKB_CB(skb)->family; | 207 | family = XFRM_SPI_SKB_CB(skb)->family; |
| 205 | 208 | ||
| 209 | /* if tunnel is present override skb->mark value with tunnel i_key */ | ||
| 210 | if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4) { | ||
| 211 | switch (family) { | ||
| 212 | case AF_INET: | ||
| 213 | mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4->parms.i_key); | ||
| 214 | break; | ||
| 215 | case AF_INET6: | ||
| 216 | mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6->parms.i_key); | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 206 | /* Allocate new secpath or COW existing one. */ | 221 | /* Allocate new secpath or COW existing one. */ |
| 207 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { | 222 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { |
| 208 | struct sec_path *sp; | 223 | struct sec_path *sp; |
| @@ -229,7 +244,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 229 | goto drop; | 244 | goto drop; |
| 230 | } | 245 | } |
| 231 | 246 | ||
| 232 | x = xfrm_state_lookup(net, skb->mark, daddr, spi, nexthdr, family); | 247 | x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family); |
| 233 | if (x == NULL) { | 248 | if (x == NULL) { |
| 234 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); | 249 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); |
| 235 | xfrm_audit_state_notfound(skb, family, spi, seq); | 250 | xfrm_audit_state_notfound(skb, family, spi, seq); |
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index dab57daae408..4fd725a0c500 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
| @@ -99,6 +99,7 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) | |||
| 99 | 99 | ||
| 100 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { | 100 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { |
| 101 | XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq; | 101 | XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq; |
| 102 | XFRM_SKB_CB(skb)->seq.output.hi = 0; | ||
| 102 | if (unlikely(x->replay.oseq == 0)) { | 103 | if (unlikely(x->replay.oseq == 0)) { |
| 103 | x->replay.oseq--; | 104 | x->replay.oseq--; |
| 104 | xfrm_audit_state_replay_overflow(x, skb); | 105 | xfrm_audit_state_replay_overflow(x, skb); |
| @@ -177,6 +178,7 @@ static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb) | |||
| 177 | 178 | ||
| 178 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { | 179 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { |
| 179 | XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq; | 180 | XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq; |
| 181 | XFRM_SKB_CB(skb)->seq.output.hi = 0; | ||
| 180 | if (unlikely(replay_esn->oseq == 0)) { | 182 | if (unlikely(replay_esn->oseq == 0)) { |
| 181 | replay_esn->oseq--; | 183 | replay_esn->oseq--; |
| 182 | xfrm_audit_state_replay_overflow(x, skb); | 184 | xfrm_audit_state_replay_overflow(x, skb); |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f5e39e35d73a..96688cd0f6f1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -927,8 +927,8 @@ struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi, | |||
| 927 | x->id.spi != spi) | 927 | x->id.spi != spi) |
| 928 | continue; | 928 | continue; |
| 929 | 929 | ||
| 930 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); | ||
| 931 | xfrm_state_hold(x); | 930 | xfrm_state_hold(x); |
| 931 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); | ||
| 932 | return x; | 932 | return x; |
| 933 | } | 933 | } |
| 934 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); | 934 | spin_unlock_bh(&net->xfrm.xfrm_state_lock); |
