diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-02 13:36:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-02 13:36:41 -0400 |
commit | bb6bbc7ca2254fd885f5b85f4cc0cda7cf04f8c1 (patch) | |
tree | 00ea99c4249a670f2325b84fc177a7a182f10e86 /net | |
parent | f51fdffad5b7709d0ade40736b58a2da2707fa15 (diff) | |
parent | 1cceda7849809a8857fd9f26efe8846506c710e1 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) Fix wrong TCP checksums on MTU probing when checksum offloading is
disabled, from Douglas Caetano dos Santos.
2) Fix qdisc backlog updates in qfq and sfb schedulers, from Cong Wang.
3) Route lookup flow key protocol value is wrong in ip6gre_xmit_other(),
fix from Lance Richardson.
4) Scheduling while atomic in multicast routing code of ipv4 and ipv6,
fix from Nikolay Aleksandrov.
5) Fix packet alignment in fec driver, from Eric Nelson.
6) Fix perf regression in sctp due to struct layout and cache misses,
from Xin Long.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
sctp: fix the issue sctp_diag uses lock_sock in rcu_read_lock
sctp: change to check peer prsctp_capable when using prsctp polices
sctp: remove prsctp_param from sctp_chunk
sctp: move sent_count to the memory hole in sctp_chunk
tg3: Avoid NULL pointer dereference in tg3_io_error_detected()
act_ife: Fix false encoding
act_ife: Fix external mac header on encode
VSOCK: Don't dec ack backlog twice for rejected connections
Revert "net: ethernet: bcmgenet: use phydev from struct net_device"
net: fec: align IP header in hardware
net: fec: remove QUIRK_HAS_RACC from i.mx27
net: fec: remove QUIRK_HAS_RACC from i.mx25
ipmr, ip6mr: fix scheduling while atomic and a deadlock with ipmr_get_route
ip6_gre: fix flowi6_proto value in ip6gre_xmit_other()
tcp: fix a compile error in DBGUNDO()
tcp: fix wrong checksum calculation on MTU probing
sch_sfb: keep backlog updated with qlen
sch_qfq: keep backlog updated with qlen
can: dev: fix deadlock reported after bus-off
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ipmr.c | 3 | ||||
-rw-r--r-- | net/ipv4/route.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 12 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 5 | ||||
-rw-r--r-- | net/ipv6/route.c | 4 | ||||
-rw-r--r-- | net/sched/act_ife.c | 7 | ||||
-rw-r--r-- | net/sched/sch_qfq.c | 3 | ||||
-rw-r--r-- | net/sched/sch_sfb.c | 3 | ||||
-rw-r--r-- | net/sctp/chunk.c | 11 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 12 | ||||
-rw-r--r-- | net/sctp/sctp_diag.c | 58 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 15 | ||||
-rw-r--r-- | net/sctp/socket.c | 10 | ||||
-rw-r--r-- | net/vmw_vsock/af_vsock.c | 6 |
16 files changed, 91 insertions, 65 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index a87bcd2d4a94..5f006e13de56 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -2123,7 +2123,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | |||
2123 | 2123 | ||
2124 | int ipmr_get_route(struct net *net, struct sk_buff *skb, | 2124 | int ipmr_get_route(struct net *net, struct sk_buff *skb, |
2125 | __be32 saddr, __be32 daddr, | 2125 | __be32 saddr, __be32 daddr, |
2126 | struct rtmsg *rtm, int nowait) | 2126 | struct rtmsg *rtm, int nowait, u32 portid) |
2127 | { | 2127 | { |
2128 | struct mfc_cache *cache; | 2128 | struct mfc_cache *cache; |
2129 | struct mr_table *mrt; | 2129 | struct mr_table *mrt; |
@@ -2168,6 +2168,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, | |||
2168 | return -ENOMEM; | 2168 | return -ENOMEM; |
2169 | } | 2169 | } |
2170 | 2170 | ||
2171 | NETLINK_CB(skb2).portid = portid; | ||
2171 | skb_push(skb2, sizeof(struct iphdr)); | 2172 | skb_push(skb2, sizeof(struct iphdr)); |
2172 | skb_reset_network_header(skb2); | 2173 | skb_reset_network_header(skb2); |
2173 | iph = ip_hdr(skb2); | 2174 | iph = ip_hdr(skb2); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b5b47a26d4ec..62c3ed0b7556 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -2503,7 +2503,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id, | |||
2503 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { | 2503 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { |
2504 | int err = ipmr_get_route(net, skb, | 2504 | int err = ipmr_get_route(net, skb, |
2505 | fl4->saddr, fl4->daddr, | 2505 | fl4->saddr, fl4->daddr, |
2506 | r, nowait); | 2506 | r, nowait, portid); |
2507 | |||
2507 | if (err <= 0) { | 2508 | if (err <= 0) { |
2508 | if (!nowait) { | 2509 | if (!nowait) { |
2509 | if (err == 0) | 2510 | if (err == 0) |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 08323bd95f2a..a756b8749a26 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2329,10 +2329,9 @@ static void DBGUNDO(struct sock *sk, const char *msg) | |||
2329 | } | 2329 | } |
2330 | #if IS_ENABLED(CONFIG_IPV6) | 2330 | #if IS_ENABLED(CONFIG_IPV6) |
2331 | else if (sk->sk_family == AF_INET6) { | 2331 | else if (sk->sk_family == AF_INET6) { |
2332 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
2333 | pr_debug("Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n", | 2332 | pr_debug("Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n", |
2334 | msg, | 2333 | msg, |
2335 | &np->daddr, ntohs(inet->inet_dport), | 2334 | &sk->sk_v6_daddr, ntohs(inet->inet_dport), |
2336 | tp->snd_cwnd, tcp_left_out(tp), | 2335 | tp->snd_cwnd, tcp_left_out(tp), |
2337 | tp->snd_ssthresh, tp->prior_ssthresh, | 2336 | tp->snd_ssthresh, tp->prior_ssthresh, |
2338 | tp->packets_out); | 2337 | tp->packets_out); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5288cec4a2b2..d48d5571e62a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1966,12 +1966,14 @@ static int tcp_mtu_probe(struct sock *sk) | |||
1966 | len = 0; | 1966 | len = 0; |
1967 | tcp_for_write_queue_from_safe(skb, next, sk) { | 1967 | tcp_for_write_queue_from_safe(skb, next, sk) { |
1968 | copy = min_t(int, skb->len, probe_size - len); | 1968 | copy = min_t(int, skb->len, probe_size - len); |
1969 | if (nskb->ip_summed) | 1969 | if (nskb->ip_summed) { |
1970 | skb_copy_bits(skb, 0, skb_put(nskb, copy), copy); | 1970 | skb_copy_bits(skb, 0, skb_put(nskb, copy), copy); |
1971 | else | 1971 | } else { |
1972 | nskb->csum = skb_copy_and_csum_bits(skb, 0, | 1972 | __wsum csum = skb_copy_and_csum_bits(skb, 0, |
1973 | skb_put(nskb, copy), | 1973 | skb_put(nskb, copy), |
1974 | copy, nskb->csum); | 1974 | copy, 0); |
1975 | nskb->csum = csum_block_add(nskb->csum, csum, len); | ||
1976 | } | ||
1975 | 1977 | ||
1976 | if (skb->len <= copy) { | 1978 | if (skb->len <= copy) { |
1977 | /* We've eaten all the data from this skb. | 1979 | /* We've eaten all the data from this skb. |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 704274cbd495..edc3daab354e 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -648,7 +648,6 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev) | |||
648 | encap_limit = t->parms.encap_limit; | 648 | encap_limit = t->parms.encap_limit; |
649 | 649 | ||
650 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); | 650 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); |
651 | fl6.flowi6_proto = skb->protocol; | ||
652 | 651 | ||
653 | err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); | 652 | err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); |
654 | if (err) | 653 | if (err) |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index fccb5dd91902..7f4265b1649b 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -2285,8 +2285,8 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, | |||
2285 | return 1; | 2285 | return 1; |
2286 | } | 2286 | } |
2287 | 2287 | ||
2288 | int ip6mr_get_route(struct net *net, | 2288 | int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, |
2289 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 2289 | int nowait, u32 portid) |
2290 | { | 2290 | { |
2291 | int err; | 2291 | int err; |
2292 | struct mr6_table *mrt; | 2292 | struct mr6_table *mrt; |
@@ -2331,6 +2331,7 @@ int ip6mr_get_route(struct net *net, | |||
2331 | return -ENOMEM; | 2331 | return -ENOMEM; |
2332 | } | 2332 | } |
2333 | 2333 | ||
2334 | NETLINK_CB(skb2).portid = portid; | ||
2334 | skb_reset_transport_header(skb2); | 2335 | skb_reset_transport_header(skb2); |
2335 | 2336 | ||
2336 | skb_put(skb2, sizeof(struct ipv6hdr)); | 2337 | skb_put(skb2, sizeof(struct ipv6hdr)); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e3a224b97905..269218aacbea 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -3202,7 +3202,9 @@ static int rt6_fill_node(struct net *net, | |||
3202 | if (iif) { | 3202 | if (iif) { |
3203 | #ifdef CONFIG_IPV6_MROUTE | 3203 | #ifdef CONFIG_IPV6_MROUTE |
3204 | if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { | 3204 | if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { |
3205 | int err = ip6mr_get_route(net, skb, rtm, nowait); | 3205 | int err = ip6mr_get_route(net, skb, rtm, nowait, |
3206 | portid); | ||
3207 | |||
3206 | if (err <= 0) { | 3208 | if (err <= 0) { |
3207 | if (!nowait) { | 3209 | if (!nowait) { |
3208 | if (err == 0) | 3210 | if (err == 0) |
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index e87cd81315e1..4a60cd5e1875 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c | |||
@@ -53,7 +53,7 @@ int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, const void *dval) | |||
53 | u32 *tlv = (u32 *)(skbdata); | 53 | u32 *tlv = (u32 *)(skbdata); |
54 | u16 totlen = nla_total_size(dlen); /*alignment + hdr */ | 54 | u16 totlen = nla_total_size(dlen); /*alignment + hdr */ |
55 | char *dptr = (char *)tlv + NLA_HDRLEN; | 55 | char *dptr = (char *)tlv + NLA_HDRLEN; |
56 | u32 htlv = attrtype << 16 | dlen; | 56 | u32 htlv = attrtype << 16 | (dlen + NLA_HDRLEN); |
57 | 57 | ||
58 | *tlv = htonl(htlv); | 58 | *tlv = htonl(htlv); |
59 | memset(dptr, 0, totlen - NLA_HDRLEN); | 59 | memset(dptr, 0, totlen - NLA_HDRLEN); |
@@ -627,7 +627,7 @@ static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, | |||
627 | struct tcf_ife_info *ife = to_ife(a); | 627 | struct tcf_ife_info *ife = to_ife(a); |
628 | int action = ife->tcf_action; | 628 | int action = ife->tcf_action; |
629 | struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; | 629 | struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; |
630 | u16 ifehdrln = ifehdr->metalen; | 630 | int ifehdrln = (int)ifehdr->metalen; |
631 | struct meta_tlvhdr *tlv = (struct meta_tlvhdr *)(ifehdr->tlv_data); | 631 | struct meta_tlvhdr *tlv = (struct meta_tlvhdr *)(ifehdr->tlv_data); |
632 | 632 | ||
633 | spin_lock(&ife->tcf_lock); | 633 | spin_lock(&ife->tcf_lock); |
@@ -740,8 +740,6 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, | |||
740 | return TC_ACT_SHOT; | 740 | return TC_ACT_SHOT; |
741 | } | 741 | } |
742 | 742 | ||
743 | iethh = eth_hdr(skb); | ||
744 | |||
745 | err = skb_cow_head(skb, hdrm); | 743 | err = skb_cow_head(skb, hdrm); |
746 | if (unlikely(err)) { | 744 | if (unlikely(err)) { |
747 | ife->tcf_qstats.drops++; | 745 | ife->tcf_qstats.drops++; |
@@ -752,6 +750,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, | |||
752 | if (!(at & AT_EGRESS)) | 750 | if (!(at & AT_EGRESS)) |
753 | skb_push(skb, skb->dev->hard_header_len); | 751 | skb_push(skb, skb->dev->hard_header_len); |
754 | 752 | ||
753 | iethh = (struct ethhdr *)skb->data; | ||
755 | __skb_push(skb, hdrm); | 754 | __skb_push(skb, hdrm); |
756 | memcpy(skb->data, iethh, skb->mac_len); | 755 | memcpy(skb->data, iethh, skb->mac_len); |
757 | skb_reset_mac_header(skb); | 756 | skb_reset_mac_header(skb); |
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index f27ffee106f6..ca0516e6f743 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c | |||
@@ -1153,6 +1153,7 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch) | |||
1153 | if (!skb) | 1153 | if (!skb) |
1154 | return NULL; | 1154 | return NULL; |
1155 | 1155 | ||
1156 | qdisc_qstats_backlog_dec(sch, skb); | ||
1156 | sch->q.qlen--; | 1157 | sch->q.qlen--; |
1157 | qdisc_bstats_update(sch, skb); | 1158 | qdisc_bstats_update(sch, skb); |
1158 | 1159 | ||
@@ -1256,6 +1257,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, | |||
1256 | } | 1257 | } |
1257 | 1258 | ||
1258 | bstats_update(&cl->bstats, skb); | 1259 | bstats_update(&cl->bstats, skb); |
1260 | qdisc_qstats_backlog_inc(sch, skb); | ||
1259 | ++sch->q.qlen; | 1261 | ++sch->q.qlen; |
1260 | 1262 | ||
1261 | agg = cl->agg; | 1263 | agg = cl->agg; |
@@ -1476,6 +1478,7 @@ static void qfq_reset_qdisc(struct Qdisc *sch) | |||
1476 | qdisc_reset(cl->qdisc); | 1478 | qdisc_reset(cl->qdisc); |
1477 | } | 1479 | } |
1478 | } | 1480 | } |
1481 | sch->qstats.backlog = 0; | ||
1479 | sch->q.qlen = 0; | 1482 | sch->q.qlen = 0; |
1480 | } | 1483 | } |
1481 | 1484 | ||
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index add3cc7d37ec..20a350bd1b1d 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c | |||
@@ -400,6 +400,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch, | |||
400 | enqueue: | 400 | enqueue: |
401 | ret = qdisc_enqueue(skb, child, to_free); | 401 | ret = qdisc_enqueue(skb, child, to_free); |
402 | if (likely(ret == NET_XMIT_SUCCESS)) { | 402 | if (likely(ret == NET_XMIT_SUCCESS)) { |
403 | qdisc_qstats_backlog_inc(sch, skb); | ||
403 | sch->q.qlen++; | 404 | sch->q.qlen++; |
404 | increment_qlen(skb, q); | 405 | increment_qlen(skb, q); |
405 | } else if (net_xmit_drop_count(ret)) { | 406 | } else if (net_xmit_drop_count(ret)) { |
@@ -428,6 +429,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch) | |||
428 | 429 | ||
429 | if (skb) { | 430 | if (skb) { |
430 | qdisc_bstats_update(sch, skb); | 431 | qdisc_bstats_update(sch, skb); |
432 | qdisc_qstats_backlog_dec(sch, skb); | ||
431 | sch->q.qlen--; | 433 | sch->q.qlen--; |
432 | decrement_qlen(skb, q); | 434 | decrement_qlen(skb, q); |
433 | } | 435 | } |
@@ -450,6 +452,7 @@ static void sfb_reset(struct Qdisc *sch) | |||
450 | struct sfb_sched_data *q = qdisc_priv(sch); | 452 | struct sfb_sched_data *q = qdisc_priv(sch); |
451 | 453 | ||
452 | qdisc_reset(q->qdisc); | 454 | qdisc_reset(q->qdisc); |
455 | sch->qstats.backlog = 0; | ||
453 | sch->q.qlen = 0; | 456 | sch->q.qlen = 0; |
454 | q->slot = 0; | 457 | q->slot = 0; |
455 | q->double_buffering = false; | 458 | q->double_buffering = false; |
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index a55e54738b81..0a3dbec0a8fb 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -179,6 +179,11 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
179 | msg, msg->expires_at, jiffies); | 179 | msg, msg->expires_at, jiffies); |
180 | } | 180 | } |
181 | 181 | ||
182 | if (asoc->peer.prsctp_capable && | ||
183 | SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags)) | ||
184 | msg->expires_at = | ||
185 | jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive); | ||
186 | |||
182 | /* This is the biggest possible DATA chunk that can fit into | 187 | /* This is the biggest possible DATA chunk that can fit into |
183 | * the packet | 188 | * the packet |
184 | */ | 189 | */ |
@@ -335,7 +340,7 @@ errout: | |||
335 | /* Check whether this message has expired. */ | 340 | /* Check whether this message has expired. */ |
336 | int sctp_chunk_abandoned(struct sctp_chunk *chunk) | 341 | int sctp_chunk_abandoned(struct sctp_chunk *chunk) |
337 | { | 342 | { |
338 | if (!chunk->asoc->prsctp_enable || | 343 | if (!chunk->asoc->peer.prsctp_capable || |
339 | !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) { | 344 | !SCTP_PR_POLICY(chunk->sinfo.sinfo_flags)) { |
340 | struct sctp_datamsg *msg = chunk->msg; | 345 | struct sctp_datamsg *msg = chunk->msg; |
341 | 346 | ||
@@ -349,14 +354,14 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) | |||
349 | } | 354 | } |
350 | 355 | ||
351 | if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && | 356 | if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && |
352 | time_after(jiffies, chunk->prsctp_param)) { | 357 | time_after(jiffies, chunk->msg->expires_at)) { |
353 | if (chunk->sent_count) | 358 | if (chunk->sent_count) |
354 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++; | 359 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++; |
355 | else | 360 | else |
356 | chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; | 361 | chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; |
357 | return 1; | 362 | return 1; |
358 | } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && | 363 | } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && |
359 | chunk->sent_count > chunk->prsctp_param) { | 364 | chunk->sent_count > chunk->sinfo.sinfo_timetolive) { |
360 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; | 365 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; |
361 | return 1; | 366 | return 1; |
362 | } | 367 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 72e54a416af6..107233da5cc9 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -326,7 +326,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk, gfp_t gfp) | |||
326 | 326 | ||
327 | sctp_chunk_hold(chunk); | 327 | sctp_chunk_hold(chunk); |
328 | sctp_outq_tail_data(q, chunk); | 328 | sctp_outq_tail_data(q, chunk); |
329 | if (chunk->asoc->prsctp_enable && | 329 | if (chunk->asoc->peer.prsctp_capable && |
330 | SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) | 330 | SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) |
331 | chunk->asoc->sent_cnt_removable++; | 331 | chunk->asoc->sent_cnt_removable++; |
332 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) | 332 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) |
@@ -383,7 +383,7 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, | |||
383 | 383 | ||
384 | list_for_each_entry_safe(chk, temp, queue, transmitted_list) { | 384 | list_for_each_entry_safe(chk, temp, queue, transmitted_list) { |
385 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | 385 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || |
386 | chk->prsctp_param <= sinfo->sinfo_timetolive) | 386 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) |
387 | continue; | 387 | continue; |
388 | 388 | ||
389 | list_del_init(&chk->transmitted_list); | 389 | list_del_init(&chk->transmitted_list); |
@@ -418,7 +418,7 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, | |||
418 | 418 | ||
419 | list_for_each_entry_safe(chk, temp, queue, list) { | 419 | list_for_each_entry_safe(chk, temp, queue, list) { |
420 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | 420 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || |
421 | chk->prsctp_param <= sinfo->sinfo_timetolive) | 421 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) |
422 | continue; | 422 | continue; |
423 | 423 | ||
424 | list_del_init(&chk->list); | 424 | list_del_init(&chk->list); |
@@ -442,7 +442,7 @@ void sctp_prsctp_prune(struct sctp_association *asoc, | |||
442 | { | 442 | { |
443 | struct sctp_transport *transport; | 443 | struct sctp_transport *transport; |
444 | 444 | ||
445 | if (!asoc->prsctp_enable || !asoc->sent_cnt_removable) | 445 | if (!asoc->peer.prsctp_capable || !asoc->sent_cnt_removable) |
446 | return; | 446 | return; |
447 | 447 | ||
448 | msg_len = sctp_prsctp_prune_sent(asoc, sinfo, | 448 | msg_len = sctp_prsctp_prune_sent(asoc, sinfo, |
@@ -1055,7 +1055,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) | |||
1055 | 1055 | ||
1056 | /* Mark as failed send. */ | 1056 | /* Mark as failed send. */ |
1057 | sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM); | 1057 | sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM); |
1058 | if (asoc->prsctp_enable && | 1058 | if (asoc->peer.prsctp_capable && |
1059 | SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) | 1059 | SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) |
1060 | asoc->sent_cnt_removable--; | 1060 | asoc->sent_cnt_removable--; |
1061 | sctp_chunk_free(chunk); | 1061 | sctp_chunk_free(chunk); |
@@ -1347,7 +1347,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
1347 | tsn = ntohl(tchunk->subh.data_hdr->tsn); | 1347 | tsn = ntohl(tchunk->subh.data_hdr->tsn); |
1348 | if (TSN_lte(tsn, ctsn)) { | 1348 | if (TSN_lte(tsn, ctsn)) { |
1349 | list_del_init(&tchunk->transmitted_list); | 1349 | list_del_init(&tchunk->transmitted_list); |
1350 | if (asoc->prsctp_enable && | 1350 | if (asoc->peer.prsctp_capable && |
1351 | SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) | 1351 | SCTP_PR_PRIO_ENABLED(chunk->sinfo.sinfo_flags)) |
1352 | asoc->sent_cnt_removable--; | 1352 | asoc->sent_cnt_removable--; |
1353 | sctp_chunk_free(tchunk); | 1353 | sctp_chunk_free(tchunk); |
diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c index f3508aa75815..cef0cee182d4 100644 --- a/net/sctp/sctp_diag.c +++ b/net/sctp/sctp_diag.c | |||
@@ -272,28 +272,17 @@ out: | |||
272 | return err; | 272 | return err; |
273 | } | 273 | } |
274 | 274 | ||
275 | static int sctp_tsp_dump(struct sctp_transport *tsp, void *p) | 275 | static int sctp_sock_dump(struct sock *sk, void *p) |
276 | { | 276 | { |
277 | struct sctp_endpoint *ep = tsp->asoc->ep; | 277 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
278 | struct sctp_comm_param *commp = p; | 278 | struct sctp_comm_param *commp = p; |
279 | struct sock *sk = ep->base.sk; | ||
280 | struct sk_buff *skb = commp->skb; | 279 | struct sk_buff *skb = commp->skb; |
281 | struct netlink_callback *cb = commp->cb; | 280 | struct netlink_callback *cb = commp->cb; |
282 | const struct inet_diag_req_v2 *r = commp->r; | 281 | const struct inet_diag_req_v2 *r = commp->r; |
283 | struct sctp_association *assoc = | 282 | struct sctp_association *assoc; |
284 | list_entry(ep->asocs.next, struct sctp_association, asocs); | ||
285 | int err = 0; | 283 | int err = 0; |
286 | 284 | ||
287 | /* find the ep only once through the transports by this condition */ | ||
288 | if (tsp->asoc != assoc) | ||
289 | goto out; | ||
290 | |||
291 | if (r->sdiag_family != AF_UNSPEC && sk->sk_family != r->sdiag_family) | ||
292 | goto out; | ||
293 | |||
294 | lock_sock(sk); | 285 | lock_sock(sk); |
295 | if (sk != assoc->base.sk) | ||
296 | goto release; | ||
297 | list_for_each_entry(assoc, &ep->asocs, asocs) { | 286 | list_for_each_entry(assoc, &ep->asocs, asocs) { |
298 | if (cb->args[4] < cb->args[1]) | 287 | if (cb->args[4] < cb->args[1]) |
299 | goto next; | 288 | goto next; |
@@ -312,7 +301,7 @@ static int sctp_tsp_dump(struct sctp_transport *tsp, void *p) | |||
312 | cb->nlh->nlmsg_seq, | 301 | cb->nlh->nlmsg_seq, |
313 | NLM_F_MULTI, cb->nlh) < 0) { | 302 | NLM_F_MULTI, cb->nlh) < 0) { |
314 | cb->args[3] = 1; | 303 | cb->args[3] = 1; |
315 | err = 2; | 304 | err = 1; |
316 | goto release; | 305 | goto release; |
317 | } | 306 | } |
318 | cb->args[3] = 1; | 307 | cb->args[3] = 1; |
@@ -321,7 +310,7 @@ static int sctp_tsp_dump(struct sctp_transport *tsp, void *p) | |||
321 | sk_user_ns(NETLINK_CB(cb->skb).sk), | 310 | sk_user_ns(NETLINK_CB(cb->skb).sk), |
322 | NETLINK_CB(cb->skb).portid, | 311 | NETLINK_CB(cb->skb).portid, |
323 | cb->nlh->nlmsg_seq, 0, cb->nlh) < 0) { | 312 | cb->nlh->nlmsg_seq, 0, cb->nlh) < 0) { |
324 | err = 2; | 313 | err = 1; |
325 | goto release; | 314 | goto release; |
326 | } | 315 | } |
327 | next: | 316 | next: |
@@ -333,10 +322,35 @@ next: | |||
333 | cb->args[4] = 0; | 322 | cb->args[4] = 0; |
334 | release: | 323 | release: |
335 | release_sock(sk); | 324 | release_sock(sk); |
325 | sock_put(sk); | ||
336 | return err; | 326 | return err; |
327 | } | ||
328 | |||
329 | static int sctp_get_sock(struct sctp_transport *tsp, void *p) | ||
330 | { | ||
331 | struct sctp_endpoint *ep = tsp->asoc->ep; | ||
332 | struct sctp_comm_param *commp = p; | ||
333 | struct sock *sk = ep->base.sk; | ||
334 | struct netlink_callback *cb = commp->cb; | ||
335 | const struct inet_diag_req_v2 *r = commp->r; | ||
336 | struct sctp_association *assoc = | ||
337 | list_entry(ep->asocs.next, struct sctp_association, asocs); | ||
338 | |||
339 | /* find the ep only once through the transports by this condition */ | ||
340 | if (tsp->asoc != assoc) | ||
341 | goto out; | ||
342 | |||
343 | if (r->sdiag_family != AF_UNSPEC && sk->sk_family != r->sdiag_family) | ||
344 | goto out; | ||
345 | |||
346 | sock_hold(sk); | ||
347 | cb->args[5] = (long)sk; | ||
348 | |||
349 | return 1; | ||
350 | |||
337 | out: | 351 | out: |
338 | cb->args[2]++; | 352 | cb->args[2]++; |
339 | return err; | 353 | return 0; |
340 | } | 354 | } |
341 | 355 | ||
342 | static int sctp_ep_dump(struct sctp_endpoint *ep, void *p) | 356 | static int sctp_ep_dump(struct sctp_endpoint *ep, void *p) |
@@ -472,10 +486,18 @@ skip: | |||
472 | * 2 : to record the transport pos of this time's traversal | 486 | * 2 : to record the transport pos of this time's traversal |
473 | * 3 : to mark if we have dumped the ep info of the current asoc | 487 | * 3 : to mark if we have dumped the ep info of the current asoc |
474 | * 4 : to work as a temporary variable to traversal list | 488 | * 4 : to work as a temporary variable to traversal list |
489 | * 5 : to save the sk we get from travelsing the tsp list. | ||
475 | */ | 490 | */ |
476 | if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE))) | 491 | if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE))) |
477 | goto done; | 492 | goto done; |
478 | sctp_for_each_transport(sctp_tsp_dump, net, cb->args[2], &commp); | 493 | |
494 | next: | ||
495 | cb->args[5] = 0; | ||
496 | sctp_for_each_transport(sctp_get_sock, net, cb->args[2], &commp); | ||
497 | |||
498 | if (cb->args[5] && !sctp_sock_dump((struct sock *)cb->args[5], &commp)) | ||
499 | goto next; | ||
500 | |||
479 | done: | 501 | done: |
480 | cb->args[1] = cb->args[4]; | 502 | cb->args[1] = cb->args[4]; |
481 | cb->args[4] = 0; | 503 | cb->args[4] = 0; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 8c77b87a8565..46ffecc57214 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -706,20 +706,6 @@ nodata: | |||
706 | return retval; | 706 | return retval; |
707 | } | 707 | } |
708 | 708 | ||
709 | static void sctp_set_prsctp_policy(struct sctp_chunk *chunk, | ||
710 | const struct sctp_sndrcvinfo *sinfo) | ||
711 | { | ||
712 | if (!chunk->asoc->prsctp_enable) | ||
713 | return; | ||
714 | |||
715 | if (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags)) | ||
716 | chunk->prsctp_param = | ||
717 | jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive); | ||
718 | else if (SCTP_PR_RTX_ENABLED(sinfo->sinfo_flags) || | ||
719 | SCTP_PR_PRIO_ENABLED(sinfo->sinfo_flags)) | ||
720 | chunk->prsctp_param = sinfo->sinfo_timetolive; | ||
721 | } | ||
722 | |||
723 | /* Make a DATA chunk for the given association from the provided | 709 | /* Make a DATA chunk for the given association from the provided |
724 | * parameters. However, do not populate the data payload. | 710 | * parameters. However, do not populate the data payload. |
725 | */ | 711 | */ |
@@ -753,7 +739,6 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc, | |||
753 | 739 | ||
754 | retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp); | 740 | retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp); |
755 | memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo)); | 741 | memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo)); |
756 | sctp_set_prsctp_policy(retval, sinfo); | ||
757 | 742 | ||
758 | nodata: | 743 | nodata: |
759 | return retval; | 744 | return retval; |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9fc417a8b476..8ed2d99bde6d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -4469,17 +4469,21 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), | |||
4469 | const union sctp_addr *paddr, void *p) | 4469 | const union sctp_addr *paddr, void *p) |
4470 | { | 4470 | { |
4471 | struct sctp_transport *transport; | 4471 | struct sctp_transport *transport; |
4472 | int err = 0; | 4472 | int err = -ENOENT; |
4473 | 4473 | ||
4474 | rcu_read_lock(); | 4474 | rcu_read_lock(); |
4475 | transport = sctp_addrs_lookup_transport(net, laddr, paddr); | 4475 | transport = sctp_addrs_lookup_transport(net, laddr, paddr); |
4476 | if (!transport || !sctp_transport_hold(transport)) | 4476 | if (!transport || !sctp_transport_hold(transport)) |
4477 | goto out; | 4477 | goto out; |
4478 | err = cb(transport, p); | 4478 | |
4479 | sctp_association_hold(transport->asoc); | ||
4479 | sctp_transport_put(transport); | 4480 | sctp_transport_put(transport); |
4480 | 4481 | ||
4481 | out: | ||
4482 | rcu_read_unlock(); | 4482 | rcu_read_unlock(); |
4483 | err = cb(transport, p); | ||
4484 | sctp_association_put(transport->asoc); | ||
4485 | |||
4486 | out: | ||
4483 | return err; | 4487 | return err; |
4484 | } | 4488 | } |
4485 | EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); | 4489 | EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); |
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 17dbbe64cd73..8a398b3fb532 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
@@ -465,6 +465,8 @@ void vsock_pending_work(struct work_struct *work) | |||
465 | 465 | ||
466 | if (vsock_is_pending(sk)) { | 466 | if (vsock_is_pending(sk)) { |
467 | vsock_remove_pending(listener, sk); | 467 | vsock_remove_pending(listener, sk); |
468 | |||
469 | listener->sk_ack_backlog--; | ||
468 | } else if (!vsk->rejected) { | 470 | } else if (!vsk->rejected) { |
469 | /* We are not on the pending list and accept() did not reject | 471 | /* We are not on the pending list and accept() did not reject |
470 | * us, so we must have been accepted by our user process. We | 472 | * us, so we must have been accepted by our user process. We |
@@ -475,8 +477,6 @@ void vsock_pending_work(struct work_struct *work) | |||
475 | goto out; | 477 | goto out; |
476 | } | 478 | } |
477 | 479 | ||
478 | listener->sk_ack_backlog--; | ||
479 | |||
480 | /* We need to remove ourself from the global connected sockets list so | 480 | /* We need to remove ourself from the global connected sockets list so |
481 | * incoming packets can't find this socket, and to reduce the reference | 481 | * incoming packets can't find this socket, and to reduce the reference |
482 | * count. | 482 | * count. |
@@ -2010,5 +2010,5 @@ EXPORT_SYMBOL_GPL(vsock_core_get_transport); | |||
2010 | 2010 | ||
2011 | MODULE_AUTHOR("VMware, Inc."); | 2011 | MODULE_AUTHOR("VMware, Inc."); |
2012 | MODULE_DESCRIPTION("VMware Virtual Socket Family"); | 2012 | MODULE_DESCRIPTION("VMware Virtual Socket Family"); |
2013 | MODULE_VERSION("1.0.1.0-k"); | 2013 | MODULE_VERSION("1.0.2.0-k"); |
2014 | MODULE_LICENSE("GPL v2"); | 2014 | MODULE_LICENSE("GPL v2"); |