forked from Minki/linux
sctp: Drop ipfargok in sctp_xmit function
The ipfragok flag controls whether the packet may be fragmented either on the local host on beyond. The latter is only valid on IPv4. In fact, we never want to do the latter even on IPv4 when PMTU is enabled. This is because even though we can't fragment packets within SCTP due to the prtocol's inherent faults, we can still fragment it at IP layer. By setting the DF bit we will improve the PMTU process. RFC 2960 only says that we SHOULD clear the DF bit in this case, so we're compliant even if we set the DF bit. In fact RFC 4960 no longer has this statement. Once we make this change, we only need to control the local fragmentation. There is already a bit in the skb which controls that, local_df. So this patch sets that instead of using the ipfragok argument. The only complication is that there isn't a struct sock object per transport, so for IPv4 we have to resort to changing the pmtudisc field for every packet. This should be safe though as the protocol is single-threaded. Note that after this patch we can remove ipfragok from the rest of the stack too. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cfb266c0ee
commit
f880374c2f
@ -524,8 +524,7 @@ static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id,
|
|||||||
*/
|
*/
|
||||||
struct sctp_af {
|
struct sctp_af {
|
||||||
int (*sctp_xmit) (struct sk_buff *skb,
|
int (*sctp_xmit) (struct sk_buff *skb,
|
||||||
struct sctp_transport *,
|
struct sctp_transport *);
|
||||||
int ipfragok);
|
|
||||||
int (*setsockopt) (struct sock *sk,
|
int (*setsockopt) (struct sock *sk,
|
||||||
int level,
|
int level,
|
||||||
int optname,
|
int optname,
|
||||||
|
@ -195,8 +195,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Based on tcp_v6_xmit() in tcp_ipv6.c. */
|
/* Based on tcp_v6_xmit() in tcp_ipv6.c. */
|
||||||
static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
|
static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
|
||||||
int ipfragok)
|
|
||||||
{
|
{
|
||||||
struct sock *sk = skb->sk;
|
struct sock *sk = skb->sk;
|
||||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||||
@ -231,7 +230,10 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
|
|||||||
|
|
||||||
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
|
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
|
||||||
|
|
||||||
return ip6_xmit(sk, skb, &fl, np->opt, ipfragok);
|
if (!(transport->param_flags & SPP_PMTUD_ENABLE))
|
||||||
|
skb->local_df = 1;
|
||||||
|
|
||||||
|
return ip6_xmit(sk, skb, &fl, np->opt, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the dst cache entry for the given source and destination ip
|
/* Returns the dst cache entry for the given source and destination ip
|
||||||
|
@ -586,10 +586,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|||||||
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
|
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
|
||||||
nskb->len);
|
nskb->len);
|
||||||
|
|
||||||
if (tp->param_flags & SPP_PMTUD_ENABLE)
|
nskb->local_df = packet->ipfragok;
|
||||||
(*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
|
(*tp->af_specific->sctp_xmit)(nskb, tp);
|
||||||
else
|
|
||||||
(*tp->af_specific->sctp_xmit)(nskb, tp, 1);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
packet->size = packet->overhead;
|
packet->size = packet->overhead;
|
||||||
|
@ -862,16 +862,21 @@ static int sctp_inet_supported_addrs(const struct sctp_sock *opt,
|
|||||||
|
|
||||||
/* Wrapper routine that calls the ip transmit routine. */
|
/* Wrapper routine that calls the ip transmit routine. */
|
||||||
static inline int sctp_v4_xmit(struct sk_buff *skb,
|
static inline int sctp_v4_xmit(struct sk_buff *skb,
|
||||||
struct sctp_transport *transport, int ipfragok)
|
struct sctp_transport *transport)
|
||||||
{
|
{
|
||||||
|
struct inet_sock *inet = inet_sk(skb->sk);
|
||||||
|
|
||||||
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
|
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
|
||||||
"src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
|
"src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
|
||||||
__func__, skb, skb->len,
|
__func__, skb, skb->len,
|
||||||
NIPQUAD(skb->rtable->rt_src),
|
NIPQUAD(skb->rtable->rt_src),
|
||||||
NIPQUAD(skb->rtable->rt_dst));
|
NIPQUAD(skb->rtable->rt_dst));
|
||||||
|
|
||||||
|
inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
|
||||||
|
IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
|
||||||
|
|
||||||
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
|
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
|
||||||
return ip_queue_xmit(skb, ipfragok);
|
return ip_queue_xmit(skb, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sctp_af sctp_af_inet;
|
static struct sctp_af sctp_af_inet;
|
||||||
|
Loading…
Reference in New Issue
Block a user