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 {
int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *);
int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
......
......@@ -572,6 +572,12 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb)
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. */
static void sctp_inet6_msgname(char *msgname, int *addr_len)
{
......@@ -832,6 +838,7 @@ static struct sctp_af sctp_ipv6_specific = {
.is_any = sctp_v6_is_any,
.available = sctp_v6_available,
.skb_iif = sctp_v6_skb_iif,
.is_ce = sctp_v6_is_ce,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6,
......
......@@ -221,8 +221,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
*/
if (packet_empty) {
/* We no longer do refragmentation at all.
* Just fragment at the IP layer, if we
/* We no longer do refragmentation at all.
* Just fragment at the IP layer, if we
* actually hit this condition
*/
......@@ -419,17 +419,13 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* data sender to indicate that the end-points of the
* transport protocol are ECN-capable."
*
* If ECN capable && negotiated && it makes sense for
* this packet to support it (e.g. post ECN negotiation)
* then lets set the ECT bit
* Now setting the ECT bit all the time, as it should not cause
* any problems protocol-wise even if our peer ignores it.
*
* 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);
} else {
INET_ECN_dontxmit(nskb->sk);
}
INET_ECN_xmit(nskb->sk);
/* Set up the IP options. */
/* BUG: not implemented
......
......@@ -56,6 +56,7 @@
#include <net/sctp/sctp.h>
#include <net/addrconf.h>
#include <net/inet_common.h>
#include <net/inet_ecn.h>
/* Global data structures. */
struct sctp_protocol sctp_proto;
......@@ -491,11 +492,17 @@ void sctp_v4_get_saddr(struct sctp_association *asoc,
}
/* 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;
}
/* 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(). */
struct sock *sctp_v4_create_accept_sk(struct sock *sk,
struct sctp_association *asoc)
......@@ -829,6 +836,7 @@ struct sctp_af sctp_ipv4_specific = {
.available = sctp_v4_available,
.scope = sctp_v4_scope,
.skb_iif = sctp_v4_skb_iif,
.is_ce = sctp_v4_is_ce,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET,
......
......@@ -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));
tsn = ntohl(data_hdr->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. */
......@@ -2327,11 +2325,15 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
*/
if (!chunk->ecn_ce_done) {
struct sctp_af *af;
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. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
SCTP_U32(tsn));
}
}
......@@ -2583,11 +2585,15 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
* chunk later.
*/
if (!chunk->ecn_ce_done) {
struct sctp_af *af;
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. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
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