sctp: Fix ECN markings for IPv6
Vlad Yasevich [Wed, 4 Jun 2008 19:40:15 +0000 (12:40 -0700)]
Commit e9df2e8fd8fbc95c57dbd1d33dada66c4627b44c ("[IPV6]: Use
appropriate sock tclass setting for routing lookup.") also changed the
way that ECN capable transports mark this capability in IPv6.  As a
result, SCTP was not marking ECN capablity because the traffic class
was never set.  This patch brings back the markings for IPv6 traffic.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/net/sctp/structs.h
net/sctp/ipv6.c
net/sctp/output.c
net/sctp/protocol.c

index 714dc43..7f25195 100644 (file)
@@ -588,6 +588,7 @@ struct sctp_af {
        int             (*is_ce)        (const struct sk_buff *sk);
        void            (*seq_dump_addr)(struct seq_file *seq,
                                         union sctp_addr *addr);
+       void            (*ecn_capable)(struct sock *sk);
        __u16           net_header_len;
        int             sockaddr_len;
        sa_family_t     sa_family;
index e4aac32..a2f4d4d 100644 (file)
@@ -727,6 +727,11 @@ static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
        seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr));
 }
 
+static void sctp_v6_ecn_capable(struct sock *sk)
+{
+       inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
+}
+
 /* Initialize a PF_INET6 socket msg_name. */
 static void sctp_inet6_msgname(char *msgname, int *addr_len)
 {
@@ -997,6 +1002,7 @@ static struct sctp_af sctp_af_inet6 = {
        .skb_iif           = sctp_v6_skb_iif,
        .is_ce             = sctp_v6_is_ce,
        .seq_dump_addr     = sctp_v6_seq_dump_addr,
+       .ecn_capable       = sctp_v6_ecn_capable,
        .net_header_len    = sizeof(struct ipv6hdr),
        .sockaddr_len      = sizeof(struct sockaddr_in6),
 #ifdef CONFIG_COMPAT
index cf4f9fb..6d45bae 100644 (file)
@@ -548,7 +548,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         * Note: The works for IPv6 layer checks this bit too later
         * in transmission.  See IP6_ECN_flow_xmit().
         */
-       INET_ECN_xmit(nskb->sk);
+       (*tp->af_specific->ecn_capable)(nskb->sk);
 
        /* Set up the IP options.  */
        /* BUG: not implemented
index 56bdaf7..b435a19 100644 (file)
@@ -617,6 +617,11 @@ static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
        seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr));
 }
 
+static void sctp_v4_ecn_capable(struct sock *sk)
+{
+       INET_ECN_xmit(sk);
+}
+
 /* Event handler for inet address addition/deletion events.
  * The sctp_local_addr_list needs to be protocted by a spin lock since
  * multiple notifiers (say IPv4 and IPv6) may be running at the same
@@ -935,6 +940,7 @@ static struct sctp_af sctp_af_inet = {
        .skb_iif           = sctp_v4_skb_iif,
        .is_ce             = sctp_v4_is_ce,
        .seq_dump_addr     = sctp_v4_seq_dump_addr,
+       .ecn_capable       = sctp_v4_ecn_capable,
        .net_header_len    = sizeof(struct iphdr),
        .sockaddr_len      = sizeof(struct sockaddr_in),
 #ifdef CONFIG_COMPAT