forked from luck/tmp_suning_uos_patched
Merge master.kernel.org:/pub/scm/linux/kernel/git/vxy/lksctp-dev
This commit is contained in:
commit
559f0a2857
@ -503,6 +503,13 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu)
|
||||
return frag;
|
||||
}
|
||||
|
||||
static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
|
||||
{
|
||||
|
||||
sctp_assoc_sync_pmtu(asoc);
|
||||
asoc->pmtu_pending = 0;
|
||||
}
|
||||
|
||||
/* Walk through a list of TLV parameters. Don't trust the
|
||||
* individual parameter lengths and instead depend on
|
||||
* the chunk length to indicate when to stop. Make sure
|
||||
|
@ -912,6 +912,9 @@ struct sctp_transport {
|
||||
*/
|
||||
__u16 pathmaxrxt;
|
||||
|
||||
/* is the Path MTU update pending on this tranport */
|
||||
__u8 pmtu_pending;
|
||||
|
||||
/* PMTU : The current known path MTU. */
|
||||
__u32 pathmtu;
|
||||
|
||||
@ -1006,6 +1009,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
|
||||
void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
|
||||
unsigned long sctp_transport_timeout(struct sctp_transport *);
|
||||
void sctp_transport_reset(struct sctp_transport *);
|
||||
void sctp_transport_update_pmtu(struct sctp_transport *, u32);
|
||||
|
||||
|
||||
/* This is the structure we use to queue packets as they come into
|
||||
@ -1565,6 +1569,9 @@ struct sctp_association {
|
||||
*/
|
||||
__u16 pathmaxrxt;
|
||||
|
||||
/* Flag that path mtu update is pending */
|
||||
__u8 pmtu_pending;
|
||||
|
||||
/* Association : The smallest PMTU discovered for all of the
|
||||
* PMTU : peer's transport addresses.
|
||||
*/
|
||||
|
@ -1231,6 +1231,10 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
|
||||
/* Get the lowest pmtu of all the transports. */
|
||||
list_for_each(pos, &asoc->peer.transport_addr_list) {
|
||||
t = list_entry(pos, struct sctp_transport, transports);
|
||||
if (t->pmtu_pending && t->dst) {
|
||||
sctp_transport_update_pmtu(t, dst_mtu(t->dst));
|
||||
t->pmtu_pending = 0;
|
||||
}
|
||||
if (!pmtu || (t->pathmtu < pmtu))
|
||||
pmtu = t->pathmtu;
|
||||
}
|
||||
|
@ -367,24 +367,18 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
|
||||
void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
|
||||
struct sctp_transport *t, __u32 pmtu)
|
||||
{
|
||||
if (sock_owned_by_user(sk) || !t || (t->pathmtu == pmtu))
|
||||
if (!t || (t->pathmtu == pmtu))
|
||||
return;
|
||||
|
||||
if (sock_owned_by_user(sk)) {
|
||||
asoc->pmtu_pending = 1;
|
||||
t->pmtu_pending = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t->param_flags & SPP_PMTUD_ENABLE) {
|
||||
if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
|
||||
printk(KERN_WARNING "%s: Reported pmtu %d too low, "
|
||||
"using default minimum of %d\n",
|
||||
__FUNCTION__, pmtu,
|
||||
SCTP_DEFAULT_MINSEGMENT);
|
||||
/* Use default minimum segment size and disable
|
||||
* pmtu discovery on this transport.
|
||||
*/
|
||||
t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
|
||||
t->param_flags = (t->param_flags & ~SPP_PMTUD) |
|
||||
SPP_PMTUD_DISABLE;
|
||||
} else {
|
||||
t->pathmtu = pmtu;
|
||||
}
|
||||
/* Update transports view of the MTU */
|
||||
sctp_transport_update_pmtu(t, pmtu);
|
||||
|
||||
/* Update association pmtu. */
|
||||
sctp_assoc_sync_pmtu(asoc);
|
||||
|
@ -333,12 +333,19 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
|
||||
if (!sp->pf->bind_verify(sp, addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
/* We must either be unbound, or bind to the same port. */
|
||||
if (bp->port && (snum != bp->port)) {
|
||||
SCTP_DEBUG_PRINTK("sctp_do_bind:"
|
||||
/* We must either be unbound, or bind to the same port.
|
||||
* It's OK to allow 0 ports if we are already bound.
|
||||
* We'll just inhert an already bound port in this case
|
||||
*/
|
||||
if (bp->port) {
|
||||
if (!snum)
|
||||
snum = bp->port;
|
||||
else if (snum != bp->port) {
|
||||
SCTP_DEBUG_PRINTK("sctp_do_bind:"
|
||||
" New port %d does not match existing port "
|
||||
"%d.\n", snum, bp->port);
|
||||
return -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
|
||||
@ -1655,6 +1662,9 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (asoc->pmtu_pending)
|
||||
sctp_assoc_pending_pmtu(asoc);
|
||||
|
||||
/* If fragmentation is disabled and the message length exceeds the
|
||||
* association fragmentation point, return EMSGSIZE. The I-D
|
||||
* does not specify what this error is, but this looks like
|
||||
@ -3550,6 +3560,7 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
|
||||
struct sock *sk = asoc->base.sk;
|
||||
struct socket *sock;
|
||||
struct inet_sock *inetsk;
|
||||
struct sctp_af *af;
|
||||
int err = 0;
|
||||
|
||||
/* An association cannot be branched off from an already peeled-off
|
||||
@ -3571,8 +3582,9 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
|
||||
/* Make peeled-off sockets more like 1-1 accepted sockets.
|
||||
* Set the daddr and initialize id to something more random
|
||||
*/
|
||||
af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family);
|
||||
af->to_sk_daddr(&asoc->peer.primary_addr, sk);
|
||||
inetsk = inet_sk(sock->sk);
|
||||
inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
|
||||
inetsk->id = asoc->next_tsn ^ jiffies;
|
||||
|
||||
*sockp = sock;
|
||||
@ -4343,11 +4355,12 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
|
||||
err = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num))
|
||||
return -EFAULT;
|
||||
if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) {
|
||||
err = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
if (put_user(bytes_copied, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
err = -EFAULT;
|
||||
error:
|
||||
kfree(addrs);
|
||||
return err;
|
||||
|
@ -241,6 +241,45 @@ void sctp_transport_pmtu(struct sctp_transport *transport)
|
||||
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
|
||||
}
|
||||
|
||||
/* this is a complete rip-off from __sk_dst_check
|
||||
* the cookie is always 0 since this is how it's used in the
|
||||
* pmtu code
|
||||
*/
|
||||
static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
|
||||
{
|
||||
struct dst_entry *dst = t->dst;
|
||||
|
||||
if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) {
|
||||
dst_release(t->dst);
|
||||
t->dst = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
|
||||
{
|
||||
struct dst_entry *dst;
|
||||
|
||||
if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
|
||||
printk(KERN_WARNING "%s: Reported pmtu %d too low, "
|
||||
"using default minimum of %d\n",
|
||||
__FUNCTION__, pmtu,
|
||||
SCTP_DEFAULT_MINSEGMENT);
|
||||
/* Use default minimum segment size and disable
|
||||
* pmtu discovery on this transport.
|
||||
*/
|
||||
t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
|
||||
} else {
|
||||
t->pathmtu = pmtu;
|
||||
}
|
||||
|
||||
dst = sctp_transport_dst_check(t);
|
||||
if (dst)
|
||||
dst->ops->update_pmtu(dst, pmtu);
|
||||
}
|
||||
|
||||
/* Caches the dst entry and source address for a transport's destination
|
||||
* address.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user