Commit 09593bb6 authored by Jon Grimm's avatar Jon Grimm

[SCTP] Support SCTP ECN on ipv6.

parent 02350834
...@@ -239,6 +239,7 @@ struct sctp_af { ...@@ -239,6 +239,7 @@ struct sctp_af {
int (*is_any) (const union sctp_addr *); int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *); int (*available) (const union sctp_addr *);
int (*skb_iif) (const struct sk_buff *sk); int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk);
__u16 net_header_len; __u16 net_header_len;
int sockaddr_len; int sockaddr_len;
sa_family_t sa_family; sa_family_t sa_family;
......
...@@ -572,6 +572,12 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb) ...@@ -572,6 +572,12 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb)
return opt->iif; return opt->iif;
} }
/* Was this packet marked by Explicit Congestion Notification? */
static int sctp_v6_is_ce(const struct sk_buff *skb)
{
return *((__u32 *)(skb->nh.ipv6h)) & htonl(1<<20);
}
/* Initialize a PF_INET6 socket msg_name. */ /* Initialize a PF_INET6 socket msg_name. */
static void sctp_inet6_msgname(char *msgname, int *addr_len) static void sctp_inet6_msgname(char *msgname, int *addr_len)
{ {
...@@ -832,6 +838,7 @@ static struct sctp_af sctp_ipv6_specific = { ...@@ -832,6 +838,7 @@ static struct sctp_af sctp_ipv6_specific = {
.is_any = sctp_v6_is_any, .is_any = sctp_v6_is_any,
.available = sctp_v6_available, .available = sctp_v6_available,
.skb_iif = sctp_v6_skb_iif, .skb_iif = sctp_v6_skb_iif,
.is_ce = sctp_v6_is_ce,
.net_header_len = sizeof(struct ipv6hdr), .net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6), .sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6, .sa_family = AF_INET6,
......
...@@ -221,8 +221,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -221,8 +221,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
*/ */
if (packet_empty) { if (packet_empty) {
/* We no longer do refragmentation at all. /* We no longer do refragmentation at all.
* Just fragment at the IP layer, if we * Just fragment at the IP layer, if we
* actually hit this condition * actually hit this condition
*/ */
...@@ -419,17 +419,13 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -419,17 +419,13 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* data sender to indicate that the end-points of the * data sender to indicate that the end-points of the
* transport protocol are ECN-capable." * transport protocol are ECN-capable."
* *
* If ECN capable && negotiated && it makes sense for * Now setting the ECT bit all the time, as it should not cause
* this packet to support it (e.g. post ECN negotiation) * any problems protocol-wise even if our peer ignores it.
* then lets set the ECT bit
* *
* FIXME: Need to do something else for IPv6 * Note: The works for IPv6 layer checks this bit too later
* in transmission. See IP6_ECN_flow_xmit().
*/ */
if (packet->ecn_capable) { INET_ECN_xmit(nskb->sk);
INET_ECN_xmit(nskb->sk);
} else {
INET_ECN_dontxmit(nskb->sk);
}
/* Set up the IP options. */ /* Set up the IP options. */
/* BUG: not implemented /* BUG: not implemented
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/inet_common.h> #include <net/inet_common.h>
#include <net/inet_ecn.h>
/* Global data structures. */ /* Global data structures. */
struct sctp_protocol sctp_proto; struct sctp_protocol sctp_proto;
...@@ -491,11 +492,17 @@ void sctp_v4_get_saddr(struct sctp_association *asoc, ...@@ -491,11 +492,17 @@ void sctp_v4_get_saddr(struct sctp_association *asoc,
} }
/* What interface did this skb arrive on? */ /* What interface did this skb arrive on? */
int sctp_v4_skb_iif(const struct sk_buff *skb) static int sctp_v4_skb_iif(const struct sk_buff *skb)
{ {
return ((struct rtable *)skb->dst)->rt_iif; return ((struct rtable *)skb->dst)->rt_iif;
} }
/* Was this packet marked by Explicit Congestion Notification? */
static int sctp_v4_is_ce(const struct sk_buff *skb)
{
return INET_ECN_is_ce(skb->nh.iph->tos);
}
/* Create and initialize a new sk for the socket returned by accept(). */ /* Create and initialize a new sk for the socket returned by accept(). */
struct sock *sctp_v4_create_accept_sk(struct sock *sk, struct sock *sctp_v4_create_accept_sk(struct sock *sk,
struct sctp_association *asoc) struct sctp_association *asoc)
...@@ -829,6 +836,7 @@ struct sctp_af sctp_ipv4_specific = { ...@@ -829,6 +836,7 @@ struct sctp_af sctp_ipv4_specific = {
.available = sctp_v4_available, .available = sctp_v4_available,
.scope = sctp_v4_scope, .scope = sctp_v4_scope,
.skb_iif = sctp_v4_skb_iif, .skb_iif = sctp_v4_skb_iif,
.is_ce = sctp_v4_is_ce,
.net_header_len = sizeof(struct iphdr), .net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in), .sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET, .sa_family = AF_INET,
......
...@@ -2310,9 +2310,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, ...@@ -2310,9 +2310,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
tsn = ntohl(data_hdr->tsn); tsn = ntohl(data_hdr->tsn);
SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn); SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
SCTP_DEBUG_PRINTK("eat_data: skb->head %p.\n", chunk->skb->head);
/* ASSERT: Now skb->data is really the user data. */ /* ASSERT: Now skb->data is really the user data. */
...@@ -2327,11 +2325,15 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, ...@@ -2327,11 +2325,15 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
*/ */
if (!chunk->ecn_ce_done) { if (!chunk->ecn_ce_done) {
struct sctp_af *af;
chunk->ecn_ce_done = 1; chunk->ecn_ce_done = 1;
if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) &&
asoc->peer.ecn_capable) { af = sctp_get_af_specific(
ipver2af(chunk->skb->nh.iph->version));
if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
/* Do real work as sideffect. */ /* Do real work as sideffect. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
SCTP_U32(tsn)); SCTP_U32(tsn));
} }
} }
...@@ -2583,11 +2585,15 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep, ...@@ -2583,11 +2585,15 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
* chunk later. * chunk later.
*/ */
if (!chunk->ecn_ce_done) { if (!chunk->ecn_ce_done) {
struct sctp_af *af;
chunk->ecn_ce_done = 1; chunk->ecn_ce_done = 1;
if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) &&
asoc->peer.ecn_capable) { af = sctp_get_af_specific(
ipver2af(chunk->skb->nh.iph->version));
if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
/* Do real work as sideffect. */ /* Do real work as sideffect. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
SCTP_U32(tsn)); SCTP_U32(tsn));
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment