From 2a91aa3967398fb94eccc8da67c82bce9f67afdf Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Mon, 20 Mar 2006 17:41:47 -0800 Subject: [DCCP] CCID2: Initial CCID2 (TCP-Like) implementation Original work by Andrea Bittau, Arnaldo Melo cleaned up and fixed several issues on the merge process. For now CCID2 was turned the default for all SOCK_DCCP connections, but this will be remedied soon with the merge of the feature negotiation code. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 088529f5496..268b4579d7e 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -314,9 +314,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -/* FIXME: for now we're using CCID 3 (TFRC) */ -#define DCCPF_INITIAL_CCID 3 -#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 +/* FIXME: for now we're using CCID 2 (TCP-Like) */ +#define DCCPF_INITIAL_CCID 2 +#define DCCPF_INITIAL_SEND_ACK_VECTOR 1 /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 @@ -430,6 +430,8 @@ struct dccp_sock { struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; __u32 dccps_packet_size; + __u16 dccps_l_ack_ratio; + __u16 dccps_r_ack_ratio; unsigned long dccps_ndp_count; __u32 dccps_mss_cache; struct dccp_options dccps_options; -- cgit v1.2.3-70-g09d2 From afe00251dd9b53d51de91ff0099961f42bbf3754 Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Mon, 20 Mar 2006 17:43:56 -0800 Subject: [DCCP]: Initial feature negotiation implementation Still needs more work, but boots and doesn't crashes, even does some negotiation! 18:38:52.174934 127.0.0.1.43458 > 127.0.0.1.5001: request 18:38:52.218526 127.0.0.1.5001 > 127.0.0.1.43458: response 18:38:52.185398 127.0.0.1.43458 > 127.0.0.1.5001: :-) Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 35 +++- net/dccp/Makefile | 2 +- net/dccp/feat.c | 554 +++++++++++++++++++++++++++++++++++++++++++++++++++ net/dccp/feat.h | 28 +++ net/dccp/input.c | 3 + net/dccp/ipv4.c | 19 +- net/dccp/minisocks.c | 4 + net/dccp/options.c | 139 ++++++++++++- net/dccp/output.c | 4 + net/dccp/proto.c | 53 +++++ net/dccp/timer.c | 12 ++ 11 files changed, 847 insertions(+), 6 deletions(-) create mode 100644 net/dccp/feat.c create mode 100644 net/dccp/feat.h (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 268b4579d7e..f91c8a62406 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -154,6 +154,10 @@ enum { DCCPO_MANDATORY = 1, DCCPO_MIN_RESERVED = 3, DCCPO_MAX_RESERVED = 31, + DCCPO_CHANGE_L = 32, + DCCPO_CONFIRM_L = 33, + DCCPO_CHANGE_R = 34, + DCCPO_CONFIRM_R = 35, DCCPO_NDP_COUNT = 37, DCCPO_ACK_VECTOR_0 = 38, DCCPO_ACK_VECTOR_1 = 39, @@ -168,7 +172,9 @@ enum { /* DCCP features */ enum { DCCPF_RESERVED = 0, + DCCPF_CCID = 1, DCCPF_SEQUENCE_WINDOW = 3, + DCCPF_ACK_RATIO = 5, DCCPF_SEND_ACK_VECTOR = 6, DCCPF_SEND_NDP_COUNT = 7, /* 10-127 reserved */ @@ -176,9 +182,18 @@ enum { DCCPF_MAX_CCID_SPECIFIC = 255, }; +/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */ +struct dccp_so_feat { + __u8 dccpsf_feat; + __u8 *dccpsf_val; + __u8 dccpsf_len; +}; + /* DCCP socket options */ #define DCCP_SOCKOPT_PACKET_SIZE 1 #define DCCP_SOCKOPT_SERVICE 2 +#define DCCP_SOCKOPT_CHANGE_L 3 +#define DCCP_SOCKOPT_CHANGE_R 4 #define DCCP_SOCKOPT_CCID_RX_INFO 128 #define DCCP_SOCKOPT_CCID_TX_INFO 192 @@ -314,8 +329,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -/* FIXME: for now we're using CCID 2 (TCP-Like) */ #define DCCPF_INITIAL_CCID 2 +#define DCCPF_INITIAL_ACK_RATIO 2 #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 @@ -335,6 +350,24 @@ struct dccp_options { __u8 dccpo_tx_ccid; __u8 dccpo_send_ack_vector; __u8 dccpo_send_ndp_count; + __u8 dccpo_ack_ratio; + struct list_head dccpo_pending; + struct list_head dccpo_conf; +}; + +struct dccp_opt_conf { + __u8 *dccpoc_val; + __u8 dccpoc_len; +}; + +struct dccp_opt_pend { + struct list_head dccpop_node; + __u8 dccpop_type; + __u8 dccpop_feat; + __u8 *dccpop_val; + __u8 dccpop_len; + int dccpop_conf; + struct dccp_opt_conf *dccpop_sc; }; extern void __dccp_options_init(struct dccp_options *dccpo); diff --git a/net/dccp/Makefile b/net/dccp/Makefile index 87b27fff6e3..5736acea1c8 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile @@ -4,7 +4,7 @@ dccp_ipv6-y := ipv6.o obj-$(CONFIG_IP_DCCP) += dccp.o -dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ +dccp-y := ccid.o feat.o input.o ipv4.o minisocks.o options.o output.o proto.o \ timer.o dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o diff --git a/net/dccp/feat.c b/net/dccp/feat.c new file mode 100644 index 00000000000..99d7b7f9efa --- /dev/null +++ b/net/dccp/feat.c @@ -0,0 +1,554 @@ +/* + * net/dccp/feat.c + * + * An implementation of the DCCP protocol + * Andrea Bittau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + +#include "dccp.h" +#include "feat.h" + +#define DCCP_FEAT_SP_NOAGREE (-123) + +int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, + gfp_t gfp) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt; + + dccp_pr_debug("feat change type=%d feat=%d\n", type, feature); + + /* check if that feature is already being negotiated */ + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + /* ok we found a negotiation for this option already */ + if (opt->dccpop_feat == feature && opt->dccpop_type == type) { + dccp_pr_debug("Replacing old\n"); + /* replace */ + BUG_ON(opt->dccpop_val == NULL); + kfree(opt->dccpop_val); + opt->dccpop_val = val; + opt->dccpop_len = len; + opt->dccpop_conf = 0; + return 0; + } + } + + /* negotiation for a new feature */ + opt = kmalloc(sizeof(*opt), gfp); + if (opt == NULL) + return -ENOMEM; + + opt->dccpop_type = type; + opt->dccpop_feat = feature; + opt->dccpop_len = len; + opt->dccpop_val = val; + opt->dccpop_conf = 0; + opt->dccpop_sc = NULL; + + BUG_ON(opt->dccpop_val == NULL); + + list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_pending); + return 0; +} + +EXPORT_SYMBOL_GPL(dccp_feat_change); + +/* XXX taking only u8 vals */ +static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val) +{ + /* FIXME implement */ + dccp_pr_debug("changing [%d] feat %d to %d\n", type, feat, val); + return 0; +} + +static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, + u8 *rpref, u8 rlen) +{ + struct dccp_sock *dp = dccp_sk(sk); + u8 *spref, slen, *res = NULL; + int i, j, rc, agree = 1; + + BUG_ON(rpref == NULL); + + /* check if we are the black sheep */ + if (dp->dccps_role == DCCP_ROLE_CLIENT) { + spref = rpref; + slen = rlen; + rpref = opt->dccpop_val; + rlen = opt->dccpop_len; + } else { + spref = opt->dccpop_val; + slen = opt->dccpop_len; + } + /* + * Now we have server preference list in spref and client preference in + * rpref + */ + BUG_ON(spref == NULL); + BUG_ON(rpref == NULL); + + /* FIXME sanity check vals */ + + /* Are values in any order? XXX Lame "algorithm" here */ + /* XXX assume values are 1 byte */ + for (i = 0; i < slen; i++) { + for (j = 0; j < rlen; j++) { + if (spref[i] == rpref[j]) { + res = &spref[i]; + break; + } + } + if (res) + break; + } + + /* we didn't agree on anything */ + if (res == NULL) { + /* confirm previous value */ + switch (opt->dccpop_feat) { + case DCCPF_CCID: + /* XXX did i get this right? =P */ + if (opt->dccpop_type == DCCPO_CHANGE_L) + res = &dp->dccps_options.dccpo_tx_ccid; + else + res = &dp->dccps_options.dccpo_rx_ccid; + break; + + default: + WARN_ON(1); /* XXX implement res */ + return -EFAULT; + } + + dccp_pr_debug("Don't agree... reconfirming %d\n", *res); + agree = 0; /* this is used for mandatory options... */ + } + + /* need to put result and our preference list */ + /* XXX assume 1 byte vals */ + rlen = 1 + opt->dccpop_len; + rpref = kmalloc(rlen, GFP_ATOMIC); + if (rpref == NULL) + return -ENOMEM; + + *rpref = *res; + memcpy(&rpref[1], opt->dccpop_val, opt->dccpop_len); + + /* put it in the "confirm queue" */ + if (opt->dccpop_sc == NULL) { + opt->dccpop_sc = kmalloc(sizeof(*opt->dccpop_sc), GFP_ATOMIC); + if (opt->dccpop_sc == NULL) { + kfree(rpref); + return -ENOMEM; + } + } else { + /* recycle the confirm slot */ + BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); + kfree(opt->dccpop_sc->dccpoc_val); + dccp_pr_debug("recycling confirm slot\n"); + } + memset(opt->dccpop_sc, 0, sizeof(*opt->dccpop_sc)); + + opt->dccpop_sc->dccpoc_val = rpref; + opt->dccpop_sc->dccpoc_len = rlen; + + /* update the option on our side [we are about to send the confirm] */ + rc = dccp_feat_update(sk, opt->dccpop_type, opt->dccpop_feat, *res); + if (rc) { + kfree(opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc); + opt->dccpop_sc = 0; + return rc; + } + + dccp_pr_debug("Will confirm %d\n", *rpref); + + /* say we want to change to X but we just got a confirm X, suppress our + * change + */ + if (!opt->dccpop_conf) { + if (*opt->dccpop_val == *res) + opt->dccpop_conf = 1; + dccp_pr_debug("won't ask for change of same feature\n"); + } + + return agree ? 0 : DCCP_FEAT_SP_NOAGREE; /* used for mandatory opts */ +} + +static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt; + int rc = 1; + u8 t; + + /* + * We received a CHANGE. We gotta match it against our own preference + * list. If we got a CHANGE_R it means it's a change for us, so we need + * to compare our CHANGE_L list. + */ + if (type == DCCPO_CHANGE_L) + t = DCCPO_CHANGE_R; + else + t = DCCPO_CHANGE_L; + + /* find our preference list for this feature */ + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + if (opt->dccpop_type != t || opt->dccpop_feat != feature) + continue; + + /* find the winner from the two preference lists */ + rc = dccp_feat_reconcile(sk, opt, val, len); + break; + } + + /* We didn't deal with the change. This can happen if we have no + * preference list for the feature. In fact, it just shouldn't + * happen---if we understand a feature, we should have a preference list + * with at least the default value. + */ + BUG_ON(rc == 1); + + return rc; +} + +static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) +{ + struct dccp_opt_pend *opt; + struct dccp_sock *dp = dccp_sk(sk); + u8 *copy; + int rc; + + /* NN features must be change L */ + if (type == DCCPO_CHANGE_R) { + dccp_pr_debug("received CHANGE_R %d for NN feat %d\n", + type, feature); + return -EFAULT; + } + + /* XXX sanity check opt val */ + + /* copy option so we can confirm it */ + opt = kzalloc(sizeof(*opt), GFP_ATOMIC); + if (opt == NULL) + return -ENOMEM; + + copy = kmalloc(len, GFP_ATOMIC); + if (copy == NULL) { + kfree(opt); + return -ENOMEM; + } + memcpy(copy, val, len); + + opt->dccpop_type = DCCPO_CONFIRM_R; /* NN can only confirm R */ + opt->dccpop_feat = feature; + opt->dccpop_val = copy; + opt->dccpop_len = len; + + /* change feature */ + rc = dccp_feat_update(sk, type, feature, *val); + if (rc) { + kfree(opt->dccpop_val); + kfree(opt); + return rc; + } + + dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy); + list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); + + return 0; +} + +static void dccp_feat_empty_confirm(struct sock *sk, u8 type, u8 feature) +{ + struct dccp_sock *dp = dccp_sk(sk); + /* XXX check if other confirms for that are queued and recycle slot */ + struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC); + + if (opt == NULL) { + /* XXX what do we do? Ignoring should be fine. It's a change + * after all =P + */ + return; + } + + opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R : + DCCPO_CONFIRM_L; + opt->dccpop_feat = feature; + opt->dccpop_val = 0; + opt->dccpop_len = 0; + + /* change feature */ + dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type); + list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); +} + +static void dccp_feat_flush_confirm(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + /* Check if there is anything to confirm in the first place */ + int yes = !list_empty(&dp->dccps_options.dccpo_conf); + + if (!yes) { + struct dccp_opt_pend *opt; + + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + if (opt->dccpop_conf) { + yes = 1; + break; + } + } + } + + if (!yes) + return; + + /* OK there is something to confirm... */ + /* XXX check if packet is in flight? Send delayed ack?? */ + if (sk->sk_state == DCCP_OPEN) + dccp_send_ack(sk); +} + +int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) +{ + int rc; + + dccp_pr_debug("got feat change type=%d feat=%d\n", type, feature); + + /* figure out if it's SP or NN feature */ + switch (feature) { + /* deal with SP features */ + case DCCPF_CCID: + rc = dccp_feat_sp(sk, type, feature, val, len); + break; + + /* deal with NN features */ + case DCCPF_ACK_RATIO: + rc = dccp_feat_nn(sk, type, feature, val, len); + break; + + /* XXX implement other features */ + default: + rc = -EFAULT; + break; + } + + /* check if there were problems changing features */ + if (rc) { + /* If we don't agree on SP, we sent a confirm for old value. + * However we propagate rc to caller in case option was + * mandatory + */ + if (rc != DCCP_FEAT_SP_NOAGREE) + dccp_feat_empty_confirm(sk, type, feature); + } + + /* generate the confirm [if required] */ + dccp_feat_flush_confirm(sk); + + return rc; +} + +EXPORT_SYMBOL_GPL(dccp_feat_change_recv); + +int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len) +{ + u8 t; + struct dccp_opt_pend *opt; + struct dccp_sock *dp = dccp_sk(sk); + int rc = 1; + int all_confirmed = 1; + + dccp_pr_debug("got feat confirm type=%d feat=%d\n", type, feature); + + /* XXX sanity check type & feat */ + + /* locate our change request */ + t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L; + + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + if (!opt->dccpop_conf && opt->dccpop_type == t && + opt->dccpop_feat == feature) { + /* we found it */ + /* XXX do sanity check */ + + opt->dccpop_conf = 1; + + /* We got a confirmation---change the option */ + dccp_feat_update(sk, opt->dccpop_type, + opt->dccpop_feat, *val); + + dccp_pr_debug("feat %d type %d confirmed %d\n", + feature, type, *val); + rc = 0; + break; + } + + if (!opt->dccpop_conf) + all_confirmed = 0; + } + + /* fix re-transmit timer */ + /* XXX gotta make sure that no option negotiation occurs during + * connection shutdown. Consider that the CLOSEREQ is sent and timer is + * on. if all options are confirmed it might kill timer which should + * remain alive until close is received. + */ + if (all_confirmed) { + dccp_pr_debug("clear feat negotiation timer %p\n", sk); + inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); + } + + if (rc) + dccp_pr_debug("feat %d type %d never requested\n", + feature, type); + return 0; +} + +EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv); + +void dccp_feat_clean(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt, *next; + + list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_pending, + dccpop_node) { + BUG_ON(opt->dccpop_val == NULL); + kfree(opt->dccpop_val); + + if (opt->dccpop_sc != NULL) { + BUG_ON(opt->dccpop_sc->dccpoc_val == NULL); + kfree(opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc); + } + + kfree(opt); + } + INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + + list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, + dccpop_node) { + BUG_ON(opt == NULL); + if (opt->dccpop_val != NULL) + kfree(opt->dccpop_val); + kfree(opt); + } + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); +} + +EXPORT_SYMBOL_GPL(dccp_feat_clean); + +/* this is to be called only when a listening sock creates its child. It is + * assumed by the function---the confirm is not duplicated, but rather it is + * "passed on". + */ +int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) +{ + struct dccp_sock *olddp = dccp_sk(oldsk); + struct dccp_sock *newdp = dccp_sk(newsk); + struct dccp_opt_pend *opt; + int rc = 0; + + INIT_LIST_HEAD(&newdp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&newdp->dccps_options.dccpo_conf); + + list_for_each_entry(opt, &olddp->dccps_options.dccpo_pending, + dccpop_node) { + struct dccp_opt_pend *newopt; + /* copy the value of the option */ + u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC); + + if (val == NULL) + goto out_clean; + memcpy(val, opt->dccpop_val, opt->dccpop_len); + + newopt = kmalloc(sizeof(*newopt), GFP_ATOMIC); + if (newopt == NULL) { + kfree(val); + goto out_clean; + } + + /* insert the option */ + memcpy(newopt, opt, sizeof(*newopt)); + newopt->dccpop_val = val; + list_add_tail(&newopt->dccpop_node, + &newdp->dccps_options.dccpo_pending); + + /* XXX what happens with backlogs and multiple connections at + * once... + */ + /* the master socket no longer needs to worry about confirms */ + opt->dccpop_sc = 0; /* it's not a memleak---new socket has it */ + + /* reset state for a new socket */ + opt->dccpop_conf = 0; + } + + /* XXX not doing anything about the conf queue */ + +out: + return rc; + +out_clean: + dccp_feat_clean(newsk); + rc = -ENOMEM; + goto out; +} + +EXPORT_SYMBOL_GPL(dccp_feat_clone); + +static int __dccp_feat_init(struct sock *sk, u8 type, u8 feat, u8 *val, u8 len) +{ + int rc = -ENOMEM; + u8 *copy = kmalloc(len, GFP_KERNEL); + + if (copy != NULL) { + memcpy(copy, val, len); + rc = dccp_feat_change(sk, type, feat, copy, len, GFP_KERNEL); + if (rc) + kfree(copy); + } + return rc; +} + +int dccp_feat_init(struct sock *sk) +{ + struct dccp_sock *dp = dccp_sk(sk); + int rc; + + INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + + /* CCID L */ + rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_CCID, + &dp->dccps_options.dccpo_tx_ccid, 1); + if (rc) + goto out; + + /* CCID R */ + rc = __dccp_feat_init(sk, DCCPO_CHANGE_R, DCCPF_CCID, + &dp->dccps_options.dccpo_rx_ccid, 1); + if (rc) + goto out; + + /* Ack ratio */ + rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO, + &dp->dccps_options.dccpo_ack_ratio, 1); +out: + return rc; +} + +EXPORT_SYMBOL_GPL(dccp_feat_init); diff --git a/net/dccp/feat.h b/net/dccp/feat.h new file mode 100644 index 00000000000..67da06265f1 --- /dev/null +++ b/net/dccp/feat.h @@ -0,0 +1,28 @@ +#ifndef _DCCP_FEAT_H +#define _DCCP_FEAT_H +/* + * net/dccp/feat.h + * + * An implementation of the DCCP protocol + * Copyright (c) 2005 Andrea Bittau + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +struct sock; + +extern int dccp_feat_change(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len, gfp_t gfp); +extern int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len); +extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, + u8 *val, u8 len); +extern void dccp_feat_clean(struct sock *sk); +extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk); +extern int dccp_feat_init(struct sock *sk); + +#endif /* _DCCP_FEAT_H */ diff --git a/net/dccp/input.c b/net/dccp/input.c index b6cba72b44e..4b6d43d8b92 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -300,6 +300,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, goto out_invalid_packet; } + if (dccp_parse_options(sk, skb)) + goto out_invalid_packet; + if (dp->dccps_options.dccpo_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 38321ad8187..fcfb486f90c 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -28,6 +28,7 @@ #include "ackvec.h" #include "ccid.h" #include "dccp.h" +#include "feat.h" struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { .lhash_lock = RW_LOCK_UNLOCKED, @@ -535,7 +536,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (req == NULL) goto drop; - /* FIXME: process options */ + if (dccp_parse_options(sk, skb)) + goto drop; dccp_openreq_init(req, &dp, skb); @@ -1049,6 +1051,8 @@ int dccp_v4_init_sock(struct sock *sk) * setsockopt(CCIDs-I-want/accept). -acme */ if (likely(!dccp_ctl_socket_init)) { + int rc; + if (dp->dccps_options.dccpo_send_ack_vector) { dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); if (dp->dccps_hc_rx_ackvec == NULL) @@ -1069,8 +1073,16 @@ int dccp_v4_init_sock(struct sock *sk) dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; return -ENOMEM; } - } else + + rc = dccp_feat_init(sk); + if (rc) + return rc; + } else { + /* control socket doesn't need feat nego */ + INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); dccp_ctl_socket_init = 0; + } dccp_init_xmit_timers(sk); icsk->icsk_rto = DCCP_TIMEOUT_INIT; @@ -1118,6 +1130,9 @@ int dccp_v4_destroy_sock(struct sock *sk) ccid_exit(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; + /* clean up feature negotiation state */ + dccp_feat_clean(sk); + return 0; } diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index a60a3e948c3..9e1de5919ee 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -22,6 +22,7 @@ #include "ackvec.h" #include "ccid.h" #include "dccp.h" +#include "feat.h" struct inet_timewait_death_row dccp_death_row = { .sysctl_max_tw_buckets = NR_FILE * 2, @@ -114,6 +115,9 @@ struct sock *dccp_create_openreq_child(struct sock *sk, newicsk->icsk_rto = DCCP_TIMEOUT_INIT; do_gettimeofday(&newdp->dccps_epoch); + if (dccp_feat_clone(sk, newsk)) + goto out_free; + if (newdp->dccps_options.dccpo_send_ack_vector) { newdp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_ATOMIC); diff --git a/net/dccp/options.c b/net/dccp/options.c index 0a76426c9ae..7f99306c8e9 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -21,12 +21,14 @@ #include "ackvec.h" #include "ccid.h" #include "dccp.h" +#include "feat.h" /* stores the default values for new connection. may be changed with sysctl */ static const struct dccp_options dccpo_default_values = { .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, .dccpo_rx_ccid = DCCPF_INITIAL_CCID, .dccpo_tx_ccid = DCCPF_INITIAL_CCID, + .dccpo_ack_ratio = DCCPF_INITIAL_ACK_RATIO, .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, }; @@ -69,6 +71,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) unsigned char opt, len; unsigned char *value; u32 elapsed_time; + int rc; + int mandatory = 0; memset(opt_recv, 0, sizeof(*opt_recv)); @@ -100,6 +104,11 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) switch (opt) { case DCCPO_PADDING: break; + case DCCPO_MANDATORY: + if (mandatory) + goto out_invalid_option; + mandatory = 1; + break; case DCCPO_NDP_COUNT: if (len > 3) goto out_invalid_option; @@ -108,6 +117,31 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) dccp_pr_debug("%sNDP count=%d\n", debug_prefix, opt_recv->dccpor_ndp); break; + case DCCPO_CHANGE_L: + /* fall through */ + case DCCPO_CHANGE_R: + if (len < 2) + goto out_invalid_option; + rc = dccp_feat_change_recv(sk, opt, *value, value + 1, + len - 1); + /* + * When there is a change error, change_recv is + * responsible for dealing with it. i.e. reply with an + * empty confirm. + * If the change was mandatory, then we need to die. + */ + if (rc && mandatory) + goto out_invalid_option; + break; + case DCCPO_CONFIRM_L: + /* fall through */ + case DCCPO_CONFIRM_R: + if (len < 2) + goto out_invalid_option; + if (dccp_feat_confirm_recv(sk, opt, *value, + value + 1, len - 1)) + goto out_invalid_option; + break; case DCCPO_ACK_VECTOR_0: case DCCPO_ACK_VECTOR_1: if (pkt_type == DCCP_PKT_DATA) @@ -208,6 +242,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) sk, opt, len); break; } + + if (opt != DCCPO_MANDATORY) + mandatory = 0; } return 0; @@ -356,7 +393,7 @@ void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) { struct timeval tv; u32 now; - + dccp_timestamp(sk, &tv); now = timeval_usecs(&tv) / 10; /* yes this will overflow but that is the point as we want a @@ -402,7 +439,7 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, tstamp_echo = htonl(dp->dccps_timestamp_echo); memcpy(to, &tstamp_echo, 4); to += 4; - + if (elapsed_time_len == 2) { const u16 var16 = htons((u16)elapsed_time); memcpy(to, &var16, 2); @@ -421,6 +458,93 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, dp->dccps_timestamp_time.tv_usec = 0; } +static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, + u8 *val, u8 len) +{ + u8 *to; + + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) { + LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small" + " to insert feature %d option!\n", feat); + return -1; + } + + DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3; + + to = skb_push(skb, len + 3); + *to++ = type; + *to++ = len + 3; + *to++ = feat; + + if (len) + memcpy(to, val, len); + dccp_pr_debug("option %d feat %d len %d\n", type, feat, len); + + return 0; +} + +static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_opt_pend *opt, *next; + int change = 0; + + /* confirm any options [NN opts] */ + list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, + dccpop_node) { + dccp_insert_feat_opt(skb, opt->dccpop_type, + opt->dccpop_feat, opt->dccpop_val, + opt->dccpop_len); + /* fear empty confirms */ + if (opt->dccpop_val) + kfree(opt->dccpop_val); + kfree(opt); + } + INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + + /* see which features we need to send */ + list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, + dccpop_node) { + /* see if we need to send any confirm */ + if (opt->dccpop_sc) { + dccp_insert_feat_opt(skb, opt->dccpop_type + 1, + opt->dccpop_feat, + opt->dccpop_sc->dccpoc_val, + opt->dccpop_sc->dccpoc_len); + + BUG_ON(!opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc->dccpoc_val); + kfree(opt->dccpop_sc); + opt->dccpop_sc = NULL; + } + + /* any option not confirmed, re-send it */ + if (!opt->dccpop_conf) { + dccp_insert_feat_opt(skb, opt->dccpop_type, + opt->dccpop_feat, opt->dccpop_val, + opt->dccpop_len); + change++; + } + } + + /* Retransmit timer. + * If this is the master listening sock, we don't set a timer on it. It + * should be fine because if the dude doesn't receive our RESPONSE + * [which will contain the CHANGE] he will send another REQUEST which + * will "retrnasmit" the change. + */ + if (change && dp->dccps_role != DCCP_ROLE_LISTEN) { + dccp_pr_debug("reset feat negotiation timer %p\n", sk); + + /* XXX don't reset the timer on re-transmissions. I.e. reset it + * only when sending new stuff i guess. Currently the timer + * never backs off because on re-transmission it just resets it! + */ + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, + inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); + } +} + void dccp_insert_options(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); @@ -447,6 +571,17 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) dp->dccps_hc_tx_insert_options = 0; } + /* Feature negotiation */ + switch(DCCP_SKB_CB(skb)->dccpd_type) { + /* Data packets can't do feat negotiation */ + case DCCP_PKT_DATA: + case DCCP_PKT_DATAACK: + break; + default: + dccp_insert_feat(sk, skb); + break; + } + /* XXX: insert other options when appropriate */ if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) { diff --git a/net/dccp/output.c b/net/dccp/output.c index efd7ffb903a..0cc2bcf5652 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -64,6 +64,10 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) case DCCP_PKT_DATAACK: break; + case DCCP_PKT_REQUEST: + set_ack = 0; + /* fall through */ + case DCCP_PKT_SYNC: case DCCP_PKT_SYNCACK: ackno = dcb->dccpd_seq; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 81ad2495371..1a8cf8ecfe6 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -37,6 +37,7 @@ #include "ccid.h" #include "dccp.h" +#include "feat.h" DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; @@ -255,6 +256,39 @@ static int dccp_setsockopt_service(struct sock *sk, const u32 service, return 0; } +/* byte 1 is feature. the rest is the preference list */ +static int dccp_setsockopt_change(struct sock *sk, int type, + struct dccp_so_feat __user *optval) +{ + struct dccp_so_feat opt; + u8 *val; + int rc; + + if (copy_from_user(&opt, optval, sizeof(opt))) + return -EFAULT; + + val = kmalloc(opt.dccpsf_len, GFP_KERNEL); + if (!val) + return -ENOMEM; + + if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) { + rc = -EFAULT; + goto out_free_val; + } + + rc = dccp_feat_change(sk, type, opt.dccpsf_feat, val, opt.dccpsf_len, + GFP_KERNEL); + if (rc) + goto out_free_val; + +out: + return rc; + +out_free_val: + kfree(val); + goto out; +} + int dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { @@ -284,6 +318,25 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, case DCCP_SOCKOPT_PACKET_SIZE: dp->dccps_packet_size = val; break; + + case DCCP_SOCKOPT_CHANGE_L: + if (optlen != sizeof(struct dccp_so_feat)) + err = -EINVAL; + else + err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L, + (struct dccp_so_feat *) + optval); + break; + + case DCCP_SOCKOPT_CHANGE_R: + if (optlen != sizeof(struct dccp_so_feat)) + err = -EINVAL; + else + err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R, + (struct dccp_so_feat *) + optval); + break; + default: err = -ENOPROTOOPT; break; diff --git a/net/dccp/timer.c b/net/dccp/timer.c index aa34b576e22..d7c786608ec 100644 --- a/net/dccp/timer.c +++ b/net/dccp/timer.c @@ -141,6 +141,17 @@ static void dccp_retransmit_timer(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); + /* retransmit timer is used for feature negotiation throughout + * connection. In this case, no packet is re-transmitted, but rather an + * ack is generated and pending changes are splaced into its options. + */ + if (sk->sk_send_head == NULL) { + dccp_pr_debug("feat negotiation retransmit timeout %p\n", sk); + if (sk->sk_state == DCCP_OPEN) + dccp_send_ack(sk); + goto backoff; + } + /* * sk->sk_send_head has to have one skb with * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP @@ -177,6 +188,7 @@ static void dccp_retransmit_timer(struct sock *sk) goto out; } +backoff: icsk->icsk_backoff++; icsk->icsk_retransmits++; -- cgit v1.2.3-70-g09d2 From ba66c6e8b292997467128506f39fa6607e959050 Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Mon, 20 Mar 2006 17:56:56 -0800 Subject: [DCCP]: Set the default CCID according to kernel config selection Now CCID2 is the default, as stated in the RFC drafts, but we allow a config where just CCID3 is built, where CCID3 becomes the default. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/dccp.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index f91c8a62406..a70d1a27e7f 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -329,9 +329,18 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 -#define DCCPF_INITIAL_CCID 2 #define DCCPF_INITIAL_ACK_RATIO 2 + +#if defined(CONFIG_IP_DCCP_CCID2) || defined(CONFIG_IP_DCCP_CCID2_MODULE) +#define DCCPF_INITIAL_CCID 2 #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 +#elif defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE) +#define DCCPF_INITIAL_CCID 3 +#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 +#else +#error "At least one CCID must be built as the default" +#endif + /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 -- cgit v1.2.3-70-g09d2 From 91f0ebf7b6d5cb2b6e818d48587566144821babe Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 19:21:44 -0800 Subject: [DCCP] CCID: Improve CCID infrastructure 1. No need for ->ccid_init nor ->ccid_exit, this is what module_{init,exit} does and anynways neither ccid2 nor ccid3 were using it. 2. Rename struct ccid to struct ccid_operations and introduce struct ccid with a pointer to ccid_operations and rigth after it the rx or tx private state. 3. Remove the pointer to the state of the half connections from struct dccp_sock, now its derived thru ccid_priv() from the ccid pointer. Now we also can implement the setsockopt for changing the CCID easily as no ccid init routines can affect struct dccp_sock in any way that prevents other CCIDs from working if a CCID switch operation is asked by apps. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 2 - net/dccp/ccid.c | 188 ++++++++++++++++++++++++++++++++++++++++--------- net/dccp/ccid.h | 115 +++++++++++++----------------- net/dccp/ccids/ccid2.c | 55 +++------------ net/dccp/ccids/ccid2.h | 16 +++++ net/dccp/ccids/ccid3.c | 34 ++------- net/dccp/ccids/ccid3.h | 5 +- net/dccp/input.c | 8 --- net/dccp/ipv4.c | 24 +++---- net/dccp/minisocks.c | 25 +++---- 10 files changed, 260 insertions(+), 212 deletions(-) (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index a70d1a27e7f..bdd756cc60b 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -478,8 +478,6 @@ struct dccp_sock { __u32 dccps_mss_cache; struct dccp_options dccps_options; struct dccp_ackvec *dccps_hc_rx_ackvec; - void *dccps_hc_rx_ccid_private; - void *dccps_hc_tx_ccid_private; struct ccid *dccps_hc_rx_ccid; struct ccid *dccps_hc_tx_ccid; struct dccp_options_received dccps_options_received; diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index 06b191a5740..ff05e59043c 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c @@ -13,7 +13,7 @@ #include "ccid.h" -static struct ccid *ccids[CCID_MAX]; +static struct ccid_operations *ccids[CCID_MAX]; #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) static atomic_t ccids_lockct = ATOMIC_INIT(0); static DEFINE_SPINLOCK(ccids_lock); @@ -55,82 +55,202 @@ static inline void ccids_read_unlock(void) #define ccids_read_unlock() do { } while(0) #endif -int ccid_register(struct ccid *ccid) +static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...) { - int err; + kmem_cache_t *slab; + char slab_name_fmt[32], *slab_name; + va_list args; + + va_start(args, fmt); + vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args); + va_end(args); + + slab_name = kstrdup(slab_name_fmt, GFP_KERNEL); + if (slab_name == NULL) + return NULL; + slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (slab == NULL) + kfree(slab_name); + return slab; +} + +static void ccid_kmem_cache_destroy(kmem_cache_t *slab) +{ + if (slab != NULL) { + const char *name = kmem_cache_name(slab); + + kmem_cache_destroy(slab); + kfree(name); + } +} + +int ccid_register(struct ccid_operations *ccid_ops) +{ + int err = -ENOBUFS; + + ccid_ops->ccid_hc_rx_slab = + ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size, + "%s_hc_rx_sock", + ccid_ops->ccid_name); + if (ccid_ops->ccid_hc_rx_slab == NULL) + goto out; + + ccid_ops->ccid_hc_tx_slab = + ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size, + "%s_hc_tx_sock", + ccid_ops->ccid_name); + if (ccid_ops->ccid_hc_tx_slab == NULL) + goto out_free_rx_slab; ccids_write_lock(); err = -EEXIST; - if (ccids[ccid->ccid_id] == NULL) { - ccids[ccid->ccid_id] = ccid; + if (ccids[ccid_ops->ccid_id] == NULL) { + ccids[ccid_ops->ccid_id] = ccid_ops; err = 0; } ccids_write_unlock(); - if (err == 0) - pr_info("CCID: Registered CCID %d (%s)\n", - ccid->ccid_id, ccid->ccid_name); + if (err != 0) + goto out_free_tx_slab; + + pr_info("CCID: Registered CCID %d (%s)\n", + ccid_ops->ccid_id, ccid_ops->ccid_name); +out: return err; +out_free_tx_slab: + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); + ccid_ops->ccid_hc_tx_slab = NULL; + goto out; +out_free_rx_slab: + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); + ccid_ops->ccid_hc_rx_slab = NULL; + goto out; } EXPORT_SYMBOL_GPL(ccid_register); -int ccid_unregister(struct ccid *ccid) +int ccid_unregister(struct ccid_operations *ccid_ops) { ccids_write_lock(); - ccids[ccid->ccid_id] = NULL; + ccids[ccid_ops->ccid_id] = NULL; ccids_write_unlock(); + + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); + ccid_ops->ccid_hc_tx_slab = NULL; + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); + ccid_ops->ccid_hc_rx_slab = NULL; + pr_info("CCID: Unregistered CCID %d (%s)\n", - ccid->ccid_id, ccid->ccid_name); + ccid_ops->ccid_id, ccid_ops->ccid_name); return 0; } EXPORT_SYMBOL_GPL(ccid_unregister); -struct ccid *ccid_init(unsigned char id, struct sock *sk) +struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) { - struct ccid *ccid; + struct ccid_operations *ccid_ops; + struct ccid *ccid = NULL; + ccids_read_lock(); #ifdef CONFIG_KMOD - if (ccids[id] == NULL) + if (ccids[id] == NULL) { + /* We only try to load if in process context */ + ccids_read_unlock(); + if (gfp & GFP_ATOMIC) + goto out; request_module("net-dccp-ccid-%d", id); + ccids_read_lock(); + } #endif - ccids_read_lock(); + ccid_ops = ccids[id]; + if (ccid_ops == NULL) + goto out_unlock; - ccid = ccids[id]; - if (ccid == NULL) - goto out; + if (!try_module_get(ccid_ops->ccid_owner)) + goto out_unlock; - if (!try_module_get(ccid->ccid_owner)) - goto out_err; + ccids_read_unlock(); - if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0) + ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab : + ccid_ops->ccid_hc_tx_slab, gfp); + if (ccid == NULL) goto out_module_put; + ccid->ccid_ops = ccid_ops; + if (rx) { + memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size); + if (ccid->ccid_ops->ccid_hc_rx_init != NULL && + ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0) + goto out_free_ccid; + } else { + memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size); + if (ccid->ccid_ops->ccid_hc_tx_init != NULL && + ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0) + goto out_free_ccid; + } out: - ccids_read_unlock(); return ccid; -out_module_put: - module_put(ccid->ccid_owner); -out_err: +out_unlock: + ccids_read_unlock(); + goto out; +out_free_ccid: + kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab : + ccid_ops->ccid_hc_tx_slab, ccid); ccid = NULL; +out_module_put: + module_put(ccid_ops->ccid_owner); goto out; } -EXPORT_SYMBOL_GPL(ccid_init); +EXPORT_SYMBOL_GPL(ccid_new); -void ccid_exit(struct ccid *ccid, struct sock *sk) +struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp) { + return ccid_new(id, sk, 1, gfp); +} + +EXPORT_SYMBOL_GPL(ccid_hc_rx_new); + +struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp) +{ + return ccid_new(id, sk, 0, gfp); +} + +EXPORT_SYMBOL_GPL(ccid_hc_tx_new); + +static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx) +{ + struct ccid_operations *ccid_ops; + if (ccid == NULL) return; + ccid_ops = ccid->ccid_ops; + if (rx) { + if (ccid_ops->ccid_hc_rx_exit != NULL) + ccid_ops->ccid_hc_rx_exit(sk); + kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid); + } else { + if (ccid_ops->ccid_hc_tx_exit != NULL) + ccid_ops->ccid_hc_tx_exit(sk); + kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid); + } ccids_read_lock(); + if (ccids[ccid_ops->ccid_id] != NULL) + module_put(ccid_ops->ccid_owner); + ccids_read_unlock(); +} - if (ccids[ccid->ccid_id] != NULL) { - if (ccid->ccid_exit != NULL) - ccid->ccid_exit(sk); - module_put(ccid->ccid_owner); - } +void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk) +{ + ccid_delete(ccid, sk, 1); +} - ccids_read_unlock(); +EXPORT_SYMBOL_GPL(ccid_hc_rx_delete); + +void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk) +{ + ccid_delete(ccid, sk, 0); } -EXPORT_SYMBOL_GPL(ccid_exit); +EXPORT_SYMBOL_GPL(ccid_hc_tx_delete); diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index de681c6ad08..3dec50d4973 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -23,14 +23,16 @@ struct tcp_info; -struct ccid { +struct ccid_operations { unsigned char ccid_id; const char *ccid_name; struct module *ccid_owner; - int (*ccid_init)(struct sock *sk); - void (*ccid_exit)(struct sock *sk); - int (*ccid_hc_rx_init)(struct sock *sk); - int (*ccid_hc_tx_init)(struct sock *sk); + kmem_cache_t *ccid_hc_rx_slab; + __u32 ccid_hc_rx_obj_size; + kmem_cache_t *ccid_hc_tx_slab; + __u32 ccid_hc_tx_obj_size; + int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk); + int (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk); void (*ccid_hc_rx_exit)(struct sock *sk); void (*ccid_hc_tx_exit)(struct sock *sk); void (*ccid_hc_rx_packet_recv)(struct sock *sk, @@ -67,75 +69,58 @@ struct ccid { int __user *optlen); }; -extern int ccid_register(struct ccid *ccid); -extern int ccid_unregister(struct ccid *ccid); +extern int ccid_register(struct ccid_operations *ccid_ops); +extern int ccid_unregister(struct ccid_operations *ccid_ops); -extern struct ccid *ccid_init(unsigned char id, struct sock *sk); -extern void ccid_exit(struct ccid *ccid, struct sock *sk); +struct ccid { + struct ccid_operations *ccid_ops; + char ccid_priv[0]; +}; -static inline void __ccid_get(struct ccid *ccid) +static inline void *ccid_priv(const struct ccid *ccid) { - __module_get(ccid->ccid_owner); + return (void *)ccid->ccid_priv; } +extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, + gfp_t gfp); + +extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, + gfp_t gfp); +extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk, + gfp_t gfp); + +extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk); +extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk); + static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk, struct sk_buff *skb, int len) { int rc = 0; - if (ccid->ccid_hc_tx_send_packet != NULL) - rc = ccid->ccid_hc_tx_send_packet(sk, skb, len); + if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL) + rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len); return rc; } static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk, int more, int len) { - if (ccid->ccid_hc_tx_packet_sent != NULL) - ccid->ccid_hc_tx_packet_sent(sk, more, len); -} - -static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk) -{ - int rc = 0; - if (ccid->ccid_hc_rx_init != NULL) - rc = ccid->ccid_hc_rx_init(sk); - return rc; -} - -static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk) -{ - int rc = 0; - if (ccid->ccid_hc_tx_init != NULL) - rc = ccid->ccid_hc_tx_init(sk); - return rc; -} - -static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk) -{ - if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL && - dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL) - ccid->ccid_hc_rx_exit(sk); -} - -static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk) -{ - if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL && - dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL) - ccid->ccid_hc_tx_exit(sk); + if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL) + ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len); } static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_rx_packet_recv != NULL) - ccid->ccid_hc_rx_packet_recv(sk, skb); + if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL) + ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb); } static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_tx_packet_recv != NULL) - ccid->ccid_hc_tx_packet_recv(sk, skb); + if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL) + ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); } static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, @@ -144,8 +129,8 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, unsigned char* value) { int rc = 0; - if (ccid->ccid_hc_tx_parse_options != NULL) - rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx, + if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) + rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, value); return rc; } @@ -156,37 +141,37 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, unsigned char* value) { int rc = 0; - if (ccid->ccid_hc_rx_parse_options != NULL) - rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value); + if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) + rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); return rc; } static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_tx_insert_options != NULL) - ccid->ccid_hc_tx_insert_options(sk, skb); + if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL) + ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb); } static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, struct sk_buff *skb) { - if (ccid->ccid_hc_rx_insert_options != NULL) - ccid->ccid_hc_rx_insert_options(sk, skb); + if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL) + ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb); } static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk, struct tcp_info *info) { - if (ccid->ccid_hc_rx_get_info != NULL) - ccid->ccid_hc_rx_get_info(sk, info); + if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL) + ccid->ccid_ops->ccid_hc_rx_get_info(sk, info); } static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, struct tcp_info *info) { - if (ccid->ccid_hc_tx_get_info != NULL) - ccid->ccid_hc_tx_get_info(sk, info); + if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL) + ccid->ccid_ops->ccid_hc_tx_get_info(sk, info); } static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, @@ -194,8 +179,8 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_hc_rx_getsockopt != NULL) - rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, + if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) + rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, optval, optlen); return rc; } @@ -205,8 +190,8 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_hc_tx_getsockopt != NULL) - rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, + if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) + rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, optval, optlen); return rc; } diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 3328d23c4be..b40c4569a82 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -52,16 +52,6 @@ static int ccid2_debug; static const int ccid2_seq_len = 128; -static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk) -{ - return dccp_sk(sk)->dccps_hc_tx_ccid_private; -} - -static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk) -{ - return dccp_sk(sk)->dccps_hc_rx_ccid_private; -} - #ifdef CCID2_DEBUG static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) { @@ -707,19 +697,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid2_hc_tx_check_sanity(hctx); } -static int ccid2_hc_tx_init(struct sock *sk) +static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid2_hc_tx_sock *hctx; + struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid); int seqcount = ccid2_seq_len; int i; - dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any()); - if (dp->dccps_hc_tx_ccid_private == NULL) - return -ENOMEM; - - hctx = ccid2_hc_tx_sk(sk); - /* XXX init variables with proper values */ hctx->ccid2hctx_cwnd = 1; hctx->ccid2hctx_ssthresh = 10; @@ -728,11 +711,9 @@ static int ccid2_hc_tx_init(struct sock *sk) /* XXX init ~ to window size... */ hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * seqcount, gfp_any()); - if (hctx->ccid2hctx_seqbuf == NULL) { - kfree(dp->dccps_hc_tx_ccid_private); - dp->dccps_hc_tx_ccid_private = NULL; + if (hctx->ccid2hctx_seqbuf == NULL) return -ENOMEM; - } + for (i = 0; i < (seqcount - 1); i++) { hctx->ccid2hctx_seqbuf[i].ccid2s_next = &hctx->ccid2hctx_seqbuf[i + 1]; @@ -763,15 +744,11 @@ static int ccid2_hc_tx_init(struct sock *sk) static void ccid2_hc_tx_exit(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); ccid2_hc_tx_kill_rto_timer(sk); - kfree(hctx->ccid2hctx_seqbuf); - - kfree(dp->dccps_hc_tx_ccid_private); - dp->dccps_hc_tx_ccid_private = NULL; + hctx->ccid2hctx_seqbuf = NULL; } static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) @@ -791,33 +768,17 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) } } -static int ccid2_hc_rx_init(struct sock *sk) -{ - struct dccp_sock *dp = dccp_sk(sk); - dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock), - gfp_any()); - return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0; -} - -static void ccid2_hc_rx_exit(struct sock *sk) -{ - struct dccp_sock *dp = dccp_sk(sk); - - kfree(dp->dccps_hc_rx_ccid_private); - dp->dccps_hc_rx_ccid_private = NULL; -} - -static struct ccid ccid2 = { +static struct ccid_operations ccid2 = { .ccid_id = 2, .ccid_name = "ccid2", .ccid_owner = THIS_MODULE, + .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), .ccid_hc_tx_init = ccid2_hc_tx_init, .ccid_hc_tx_exit = ccid2_hc_tx_exit, .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, - .ccid_hc_rx_init = ccid2_hc_rx_init, - .ccid_hc_rx_exit = ccid2_hc_rx_exit, + .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock), .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, }; diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index 0b08c90955a..451a87464fa 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -20,6 +20,13 @@ #ifndef _DCCP_CCID2_H_ #define _DCCP_CCID2_H_ +#include +#include +#include +#include "../ccid.h" + +struct sock; + struct ccid2_seq { u64 ccid2s_seq; unsigned long ccid2s_sent; @@ -66,4 +73,13 @@ struct ccid2_hc_rx_sock { int ccid2hcrx_data; }; +static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk) +{ + return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid); +} + +static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk) +{ + return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); +} #endif /* _DCCP_CCID2_H_ */ diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index f9e16db09be..0587f52e4af 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -647,17 +647,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, return rc; } -static int ccid3_hc_tx_init(struct sock *sk) +static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx; - - dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any()); - if (dp->dccps_hc_tx_ccid_private == NULL) - return -ENOMEM; - - hctx = ccid3_hc_tx_sk(sk); - memset(hctx, 0, sizeof(*hctx)); + struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) @@ -680,7 +673,6 @@ static int ccid3_hc_tx_init(struct sock *sk) static void ccid3_hc_tx_exit(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); BUG_ON(hctx == NULL); @@ -690,9 +682,6 @@ static void ccid3_hc_tx_exit(struct sock *sk) /* Empty packet history */ dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); - - kfree(dp->dccps_hc_tx_ccid_private); - dp->dccps_hc_tx_ccid_private = NULL; } /* @@ -1039,20 +1028,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) } } -static int ccid3_hc_rx_init(struct sock *sk) +static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx; + struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any()); - if (dp->dccps_hc_rx_ccid_private == NULL) - return -ENOMEM; - - hcrx = ccid3_hc_rx_sk(sk); - memset(hcrx, 0, sizeof(*hcrx)); - if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) hcrx->ccid3hcrx_s = dp->dccps_packet_size; @@ -1071,7 +1053,6 @@ static int ccid3_hc_rx_init(struct sock *sk) static void ccid3_hc_rx_exit(struct sock *sk) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - struct dccp_sock *dp = dccp_sk(sk); BUG_ON(hcrx == NULL); @@ -1082,9 +1063,6 @@ static void ccid3_hc_rx_exit(struct sock *sk) /* Empty loss interval history */ dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); - - kfree(dp->dccps_hc_rx_ccid_private); - dp->dccps_hc_rx_ccid_private = NULL; } static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) @@ -1170,10 +1148,11 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, return 0; } -static struct ccid ccid3 = { +static struct ccid_operations ccid3 = { .ccid_id = 3, .ccid_name = "ccid3", .ccid_owner = THIS_MODULE, + .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), .ccid_hc_tx_init = ccid3_hc_tx_init, .ccid_hc_tx_exit = ccid3_hc_tx_exit, .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, @@ -1181,6 +1160,7 @@ static struct ccid ccid3 = { .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options, .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options, + .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock), .ccid_hc_rx_init = ccid3_hc_rx_init, .ccid_hc_rx_exit = ccid3_hc_rx_exit, .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options, diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 0bde4583d09..f18b96d4e5a 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -41,6 +41,7 @@ #include #include #include +#include "../ccid.h" #define TFRC_MIN_PACKET_SIZE 16 #define TFRC_STD_PACKET_SIZE 256 @@ -135,12 +136,12 @@ struct ccid3_hc_rx_sock { static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) { - return dccp_sk(sk)->dccps_hc_tx_ccid_private; + return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid); } static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) { - return dccp_sk(sk)->dccps_hc_rx_ccid_private; + return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); } #endif /* _DCCP_CCID3_H_ */ diff --git a/net/dccp/input.c b/net/dccp/input.c index 4b6d43d8b92..67691a0592a 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -324,14 +324,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, dccp_set_seqno(&dp->dccps_swl, max48(dp->dccps_swl, dp->dccps_isr)); - if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 || - ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) { - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); - /* FIXME: send appropriate RESET code */ - goto out_invalid_packet; - } - dccp_sync_mss(sk, icsk->icsk_pmtu_cookie); /* diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index fcfb486f90c..aa7708fed32 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1058,14 +1058,16 @@ int dccp_v4_init_sock(struct sock *sk) if (dp->dccps_hc_rx_ackvec == NULL) return -ENOMEM; } - dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid, - sk); - dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid, - sk); - if (dp->dccps_hc_rx_ccid == NULL || - dp->dccps_hc_tx_ccid == NULL) { - ccid_exit(dp->dccps_hc_rx_ccid, sk); - ccid_exit(dp->dccps_hc_tx_ccid, sk); + dp->dccps_hc_rx_ccid = + ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid, + sk, GFP_KERNEL); + dp->dccps_hc_tx_ccid = + ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid, + sk, GFP_KERNEL); + if (unlikely(dp->dccps_hc_rx_ccid == NULL || + dp->dccps_hc_tx_ccid == NULL)) { + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); if (dp->dccps_options.dccpo_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; @@ -1120,14 +1122,12 @@ int dccp_v4_destroy_sock(struct sock *sk) kfree(dp->dccps_service_list); dp->dccps_service_list = NULL; - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); if (dp->dccps_options.dccpo_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; } - ccid_exit(dp->dccps_hc_rx_ccid, sk); - ccid_exit(dp->dccps_hc_tx_ccid, sk); + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; /* clean up feature negotiation state */ diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 9e1de5919ee..5324fcacb34 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -121,23 +121,21 @@ struct sock *dccp_create_openreq_child(struct sock *sk, if (newdp->dccps_options.dccpo_send_ack_vector) { newdp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_ATOMIC); - /* - * XXX: We're using the same CCIDs set on the parent, - * i.e. sk_clone copied the master sock and left the - * CCID pointers for this child, that is why we do the - * __ccid_get calls. - */ if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) goto out_free; } - if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid, - newsk) != 0 || - ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, - newsk) != 0)) { + newdp->dccps_hc_rx_ccid = + ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid, + newsk, GFP_ATOMIC); + newdp->dccps_hc_tx_ccid = + ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid, + newsk, GFP_ATOMIC); + if (unlikely(newdp->dccps_hc_rx_ccid == NULL || + newdp->dccps_hc_tx_ccid == NULL)) { dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); - ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); - ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); + ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk); + ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk); out_free: /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ @@ -146,9 +144,6 @@ out_free: return NULL; } - __ccid_get(newdp->dccps_hc_rx_ccid); - __ccid_get(newdp->dccps_hc_tx_ccid); - /* * Step 3: Process LISTEN state * -- cgit v1.2.3-70-g09d2 From 60fe62e789076ae7c13f7ffb35fec4b24802530d Mon Sep 17 00:00:00 2001 From: Andrea Bittau Date: Mon, 20 Mar 2006 19:23:32 -0800 Subject: [DCCP]: sparse endianness annotations This also fixes the layout of dccp_hdr short sequence numbers, problem was not fatal now as we only support long (48 bits) sequence numbers. Signed-off-by: Andrea Bittau Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/dccp.h | 52 ++++++++++++++++++++------------------------------ net/dccp/ccids/ccid3.c | 6 +++--- net/dccp/dccp.h | 23 ++++++---------------- net/dccp/ipv4.c | 12 ++++++------ net/dccp/ipv6.c | 4 ++-- net/dccp/options.c | 27 +++++++++++++------------- net/dccp/proto.c | 6 +++--- 7 files changed, 54 insertions(+), 76 deletions(-) (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index bdd756cc60b..496dbad8e89 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -18,7 +18,7 @@ * @dccph_seq - sequence number high or low order 24 bits, depends on dccph_x */ struct dccp_hdr { - __u16 dccph_sport, + __be16 dccph_sport, dccph_dport; __u8 dccph_doff; #if defined(__LITTLE_ENDIAN_BITFIELD) @@ -32,18 +32,18 @@ struct dccp_hdr { #endif __u16 dccph_checksum; #if defined(__LITTLE_ENDIAN_BITFIELD) - __u32 dccph_x:1, + __u8 dccph_x:1, dccph_type:4, - dccph_reserved:3, - dccph_seq:24; + dccph_reserved:3; #elif defined(__BIG_ENDIAN_BITFIELD) - __u32 dccph_reserved:3, + __u8 dccph_reserved:3, dccph_type:4, - dccph_x:1, - dccph_seq:24; + dccph_x:1; #else #error "Adjust your defines" #endif + __u8 dccph_seq2; + __be16 dccph_seq; }; /** @@ -52,7 +52,7 @@ struct dccp_hdr { * @dccph_seq_low - low 24 bits of a 48 bit seq packet */ struct dccp_hdr_ext { - __u32 dccph_seq_low; + __be32 dccph_seq_low; }; /** @@ -62,7 +62,7 @@ struct dccp_hdr_ext { * @dccph_req_options - list of options (must be a multiple of 32 bits */ struct dccp_hdr_request { - __u32 dccph_req_service; + __be32 dccph_req_service; }; /** * struct dccp_hdr_ack_bits - acknowledgment bits common to most packets @@ -71,9 +71,9 @@ struct dccp_hdr_request { * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR */ struct dccp_hdr_ack_bits { - __u32 dccph_reserved1:8, - dccph_ack_nr_high:24; - __u32 dccph_ack_nr_low; + __be16 dccph_reserved1; + __be16 dccph_ack_nr_high; + __be32 dccph_ack_nr_low; }; /** * struct dccp_hdr_response - Conection initiation response header @@ -85,7 +85,7 @@ struct dccp_hdr_ack_bits { */ struct dccp_hdr_response { struct dccp_hdr_ack_bits dccph_resp_ack; - __u32 dccph_resp_service; + __be32 dccph_resp_service; }; /** @@ -269,16 +269,12 @@ static inline unsigned int dccp_basic_hdr_len(const struct sk_buff *skb) static inline __u64 dccp_hdr_seq(const struct sk_buff *skb) { const struct dccp_hdr *dh = dccp_hdr(skb); -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u64 seq_nr = ntohl(dh->dccph_seq << 8); -#elif defined(__BIG_ENDIAN_BITFIELD) - __u64 seq_nr = ntohl(dh->dccph_seq); -#else -#error "Adjust your defines" -#endif + __u64 seq_nr = ntohs(dh->dccph_seq); if (dh->dccph_x != 0) seq_nr = (seq_nr << 32) + ntohl(dccp_hdrx(skb)->dccph_seq_low); + else + seq_nr += (u32)dh->dccph_seq2 << 16; return seq_nr; } @@ -296,13 +292,7 @@ static inline struct dccp_hdr_ack_bits *dccp_hdr_ack_bits(const struct sk_buff * static inline u64 dccp_hdr_ack_seq(const struct sk_buff *skb) { const struct dccp_hdr_ack_bits *dhack = dccp_hdr_ack_bits(skb); -#if defined(__LITTLE_ENDIAN_BITFIELD) - return (((u64)ntohl(dhack->dccph_ack_nr_high << 8)) << 32) + ntohl(dhack->dccph_ack_nr_low); -#elif defined(__BIG_ENDIAN_BITFIELD) - return (((u64)ntohl(dhack->dccph_ack_nr_high)) << 32) + ntohl(dhack->dccph_ack_nr_low); -#else -#error "Adjust your defines" -#endif + return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) + ntohl(dhack->dccph_ack_nr_low); } static inline struct dccp_hdr_response *dccp_hdr_response(struct sk_buff *skb) @@ -387,7 +377,7 @@ struct dccp_request_sock { struct inet_request_sock dreq_inet_rsk; __u64 dreq_iss; __u64 dreq_isr; - __u32 dreq_service; + __be32 dreq_service; }; static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req) @@ -415,13 +405,13 @@ enum dccp_role { struct dccp_service_list { __u32 dccpsl_nr; - __u32 dccpsl_list[0]; + __be32 dccpsl_list[0]; }; #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) static inline int dccp_list_has_service(const struct dccp_service_list *sl, - const u32 service) + const __be32 service) { if (likely(sl != NULL)) { u32 i = sl->dccpsl_nr; @@ -467,7 +457,7 @@ struct dccp_sock { __u64 dccps_gss; __u64 dccps_gsr; __u64 dccps_gar; - __u32 dccps_service; + __be32 dccps_service; struct dccp_service_list *dccps_service_list; struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 0587f52e4af..86201631fb6 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -615,7 +615,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, __FUNCTION__, dccp_role(sk), sk); rc = -EINVAL; } else { - opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value); + opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_loss_event_rate); @@ -636,7 +636,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, __FUNCTION__, dccp_role(sk), sk); rc = -EINVAL; } else { - opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value); + opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_receive_rate); @@ -777,7 +777,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) { const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - u32 x_recv, pinv; + __be32 x_recv, pinv; BUG_ON(hcrx == NULL); diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 93f26dd6e6c..1764adb4f15 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -262,7 +262,7 @@ extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); extern int dccp_v4_checksum(const struct sk_buff *skb, - const u32 saddr, const u32 daddr); + const __be32 saddr, const __be32 daddr); extern int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code); @@ -270,7 +270,7 @@ extern void dccp_send_close(struct sock *sk, const int active); extern int dccp_invalid_packet(struct sk_buff *skb); static inline int dccp_bad_service_code(const struct sock *sk, - const __u32 service) + const __be32 service) { const struct dccp_sock *dp = dccp_sk(sk); @@ -334,27 +334,16 @@ static inline void dccp_hdr_set_seq(struct dccp_hdr *dh, const u64 gss) { struct dccp_hdr_ext *dhx = (struct dccp_hdr_ext *)((void *)dh + sizeof(*dh)); - -#if defined(__LITTLE_ENDIAN_BITFIELD) - dh->dccph_seq = htonl((gss >> 32)) >> 8; -#elif defined(__BIG_ENDIAN_BITFIELD) - dh->dccph_seq = htonl((gss >> 32)); -#else -#error "Adjust your defines" -#endif + dh->dccph_seq2 = 0; + dh->dccph_seq = htons((gss >> 32) & 0xfffff); dhx->dccph_seq_low = htonl(gss & 0xffffffff); } static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, const u64 gsr) { -#if defined(__LITTLE_ENDIAN_BITFIELD) - dhack->dccph_ack_nr_high = htonl((gsr >> 32)) >> 8; -#elif defined(__BIG_ENDIAN_BITFIELD) - dhack->dccph_ack_nr_high = htonl((gsr >> 32)); -#else -#error "Adjust your defines" -#endif + dhack->dccph_reserved1 = 0; + dhack->dccph_ack_nr_high = htons(gsr >> 32); dhack->dccph_ack_nr_low = htonl(gsr & 0xffffffff); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index aa7708fed32..be5ce57b804 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -498,9 +498,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_sock dp; struct request_sock *req; struct dccp_request_sock *dreq; - const __u32 saddr = skb->nh.iph->saddr; - const __u32 daddr = skb->nh.iph->daddr; - const __u32 service = dccp_hdr_request(skb)->dccph_req_service; + const __be32 saddr = skb->nh.iph->saddr; + const __be32 daddr = skb->nh.iph->daddr; + const __be32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; @@ -662,8 +662,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) return sk; } -int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, - const u32 daddr) +int dccp_v4_checksum(const struct sk_buff *skb, const __be32 saddr, + const __be32 daddr) { const struct dccp_hdr* dh = dccp_hdr(skb); int checksum_len; @@ -683,7 +683,7 @@ int dccp_v4_checksum(const struct sk_buff *skb, const u32 saddr, } static int dccp_v4_verify_checksum(struct sk_buff *skb, - const u32 saddr, const u32 daddr) + const __be32 saddr, const __be32 daddr) { struct dccp_hdr *dh = dccp_hdr(skb); int checksum_len; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 80c4d048869..ad5a1c66362 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -264,7 +264,7 @@ failure: } static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); @@ -678,7 +678,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_request_sock *dreq; struct inet6_request_sock *ireq6; struct ipv6_pinfo *np = inet6_sk(sk); - const __u32 service = dccp_hdr_request(skb)->dccph_req_service; + const __be32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; diff --git a/net/dccp/options.c b/net/dccp/options.c index 7f99306c8e9..7d73b33a604 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -155,7 +155,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (len != 4) goto out_invalid_option; - opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); + opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value); dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; dccp_timestamp(sk, &dp->dccps_timestamp_time); @@ -169,7 +169,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (len != 4 && len != 6 && len != 8) goto out_invalid_option; - opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value); + opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ", debug_prefix, @@ -183,9 +183,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) break; if (len == 6) - elapsed_time = ntohs(*(u16 *)(value + 4)); + elapsed_time = ntohs(*(__be16 *)(value + 4)); else - elapsed_time = ntohl(*(u32 *)(value + 4)); + elapsed_time = ntohl(*(__be32 *)(value + 4)); /* Give precedence to the biggest ELAPSED_TIME */ if (elapsed_time > opt_recv->dccpor_elapsed_time) @@ -199,9 +199,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) continue; if (len == 2) - elapsed_time = ntohs(*(u16 *)value); + elapsed_time = ntohs(*(__be16 *)value); else - elapsed_time = ntohl(*(u32 *)value); + elapsed_time = ntohl(*(__be32 *)value); if (elapsed_time > opt_recv->dccpor_elapsed_time) opt_recv->dccpor_elapsed_time = elapsed_time; @@ -358,10 +358,10 @@ void dccp_insert_option_elapsed_time(struct sock *sk, *to++ = len; if (elapsed_time_len == 2) { - const u16 var16 = htons((u16)elapsed_time); + const __be16 var16 = htons((u16)elapsed_time); memcpy(to, &var16, 2); } else { - const u32 var32 = htonl(elapsed_time); + const __be32 var32 = htonl(elapsed_time); memcpy(to, &var32, 4); } @@ -392,14 +392,13 @@ EXPORT_SYMBOL_GPL(dccp_timestamp); void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) { struct timeval tv; - u32 now; + __be32 now; dccp_timestamp(sk, &tv); - now = timeval_usecs(&tv) / 10; + now = htonl(timeval_usecs(&tv) / 10); /* yes this will overflow but that is the point as we want a * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ - now = htonl(now); dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now)); } @@ -414,7 +413,7 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, "CLIENT TX opt: " : "server TX opt: "; #endif struct timeval now; - u32 tstamp_echo; + __be32 tstamp_echo; u32 elapsed_time; int len, elapsed_time_len; unsigned char *to; @@ -441,10 +440,10 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, to += 4; if (elapsed_time_len == 2) { - const u16 var16 = htons((u16)elapsed_time); + const __be16 var16 = htons((u16)elapsed_time); memcpy(to, &var16, 2); } else if (elapsed_time_len == 4) { - const u32 var32 = htonl(elapsed_time); + const __be32 var32 = htonl(elapsed_time); memcpy(to, &var32, 4); } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 1a8cf8ecfe6..53735ee2bbd 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -221,7 +221,7 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) EXPORT_SYMBOL_GPL(dccp_ioctl); -static int dccp_setsockopt_service(struct sock *sk, const u32 service, +static int dccp_setsockopt_service(struct sock *sk, const __be32 service, char __user *optval, int optlen) { struct dccp_sock *dp = dccp_sk(sk); @@ -349,7 +349,7 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL_GPL(dccp_setsockopt); static int dccp_getsockopt_service(struct sock *sk, int len, - u32 __user *optval, + __be32 __user *optval, int __user *optlen) { const struct dccp_sock *dp = dccp_sk(sk); @@ -404,7 +404,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, break; case DCCP_SOCKOPT_SERVICE: return dccp_getsockopt_service(sk, len, - (u32 __user *)optval, optlen); + (__be32 __user *)optval, optlen); case 128 ... 191: return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, len, (u32 __user *)optval, optlen); -- cgit v1.2.3-70-g09d2 From 93ce20928f6e197707add8f670ae0cd029107e8f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 19:23:58 -0800 Subject: [DCCP]: Make CCID2 be the default As per the draft. This fixes the build when netfilter dccp components are built and dccp isn't. Thanks to Reuben Farrelly for reporting this. The following changesets will introduce /proc/sys/net/dccp/defaults/ to give more flexibility to DCCP developers and testers while apps doesn't use setsockopt to specify the desired CCID, etc. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 496dbad8e89..e35f680f909 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -320,17 +320,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) /* initial values for each feature */ #define DCCPF_INITIAL_SEQUENCE_WINDOW 100 #define DCCPF_INITIAL_ACK_RATIO 2 - -#if defined(CONFIG_IP_DCCP_CCID2) || defined(CONFIG_IP_DCCP_CCID2_MODULE) #define DCCPF_INITIAL_CCID 2 #define DCCPF_INITIAL_SEND_ACK_VECTOR 1 -#elif defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE) -#define DCCPF_INITIAL_CCID 3 -#define DCCPF_INITIAL_SEND_ACK_VECTOR 0 -#else -#error "At least one CCID must be built as the default" -#endif - /* FIXME: for now we're default to 1 but it should really be 0 */ #define DCCPF_INITIAL_SEND_NDP_COUNT 1 -- cgit v1.2.3-70-g09d2 From a4bf3902427a128455b8de299ff0918072b2e974 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 20 Mar 2006 22:50:58 -0800 Subject: [DCCP] minisock: Rename struct dccp_options to struct dccp_minisock This will later be included in struct dccp_request_sock so that we can have per connection feature negotiation state while in the 3way handshake, when we clone the DCCP_ROLE_LISTEN socket (in dccp_create_openreq_child) we'll just copy this state from dreq_minisock to dccps_minisock. Also the feature negotiation and option parsing code will mostly touch dccps_minisock, which will simplify some stuff. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/linux/dccp.h | 43 +++++++++++++++++----------- net/dccp/dccp.h | 11 ++++--- net/dccp/diag.c | 2 +- net/dccp/feat.c | 81 ++++++++++++++++++++++++---------------------------- net/dccp/input.c | 8 +++--- net/dccp/minisocks.c | 9 +++--- net/dccp/options.c | 30 +++++++++---------- net/dccp/proto.c | 23 +++++++-------- 8 files changed, 104 insertions(+), 103 deletions(-) (limited to 'include/linux/dccp.h') diff --git a/include/linux/dccp.h b/include/linux/dccp.h index e35f680f909..676333b9fad 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -328,21 +328,24 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) #define DCCP_NDP_LIMIT 0xFFFFFF /** - * struct dccp_options - option values for a DCCP connection - * @dccpo_sequence_window - Sequence Window Feature (section 7.5.2) - * @dccpo_ccid - Congestion Control Id (CCID) (section 10) - * @dccpo_send_ack_vector - Send Ack Vector Feature (section 11.5) - * @dccpo_send_ndp_count - Send NDP Count Feature (7.7.2) + * struct dccp_minisock - Minimal DCCP connection representation + * + * Will be used to pass the state from dccp_request_sock to dccp_sock. + * + * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2) + * @dccpms_ccid - Congestion Control Id (CCID) (section 10) + * @dccpms_send_ack_vector - Send Ack Vector Feature (section 11.5) + * @dccpms_send_ndp_count - Send NDP Count Feature (7.7.2) */ -struct dccp_options { - __u64 dccpo_sequence_window; - __u8 dccpo_rx_ccid; - __u8 dccpo_tx_ccid; - __u8 dccpo_send_ack_vector; - __u8 dccpo_send_ndp_count; - __u8 dccpo_ack_ratio; - struct list_head dccpo_pending; - struct list_head dccpo_conf; +struct dccp_minisock { + __u64 dccpms_sequence_window; + __u8 dccpms_rx_ccid; + __u8 dccpms_tx_ccid; + __u8 dccpms_send_ack_vector; + __u8 dccpms_send_ndp_count; + __u8 dccpms_ack_ratio; + struct list_head dccpms_pending; + struct list_head dccpms_conf; }; struct dccp_opt_conf { @@ -360,8 +363,9 @@ struct dccp_opt_pend { struct dccp_opt_conf *dccpop_sc; }; -extern void __dccp_options_init(struct dccp_options *dccpo); -extern void dccp_options_init(struct dccp_options *dccpo); +extern void __dccp_minisock_init(struct dccp_minisock *dmsk); +extern void dccp_minisock_init(struct dccp_minisock *dmsk); + extern int dccp_parse_options(struct sock *sk, struct sk_buff *skb); struct dccp_request_sock { @@ -457,7 +461,7 @@ struct dccp_sock { __u16 dccps_r_ack_ratio; unsigned long dccps_ndp_count; __u32 dccps_mss_cache; - struct dccp_options dccps_options; + struct dccp_minisock dccps_minisock; struct dccp_ackvec *dccps_hc_rx_ackvec; struct ccid *dccps_hc_rx_ccid; struct ccid *dccps_hc_tx_ccid; @@ -473,6 +477,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk) return (struct dccp_sock *)sk; } +static inline struct dccp_minisock *dccp_msk(const struct sock *sk) +{ + return (struct dccp_minisock *)&dccp_sk(sk)->dccps_minisock; +} + static inline int dccp_service_not_initialized(const struct sock *sk) { return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 47de17208d7..1fe50914868 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -303,14 +303,13 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack, static inline void dccp_update_gsr(struct sock *sk, u64 seq) { struct dccp_sock *dp = dccp_sk(sk); + const struct dccp_minisock *dmsk = dccp_msk(sk); dp->dccps_gsr = seq; dccp_set_seqno(&dp->dccps_swl, - (dp->dccps_gsr + 1 - - (dp->dccps_options.dccpo_sequence_window / 4))); + dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4)); dccp_set_seqno(&dp->dccps_swh, - (dp->dccps_gsr + - (3 * dp->dccps_options.dccpo_sequence_window) / 4)); + dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4); } static inline void dccp_update_gss(struct sock *sk, u64 seq) @@ -320,7 +319,7 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq) dp->dccps_awh = dp->dccps_gss = seq; dccp_set_seqno(&dp->dccps_awl, (dp->dccps_gss - - dp->dccps_options.dccpo_sequence_window + 1)); + dccp_msk(sk)->dccpms_sequence_window + 1)); } static inline int dccp_ack_pending(const struct sock *sk) @@ -328,7 +327,7 @@ static inline int dccp_ack_pending(const struct sock *sk) const struct dccp_sock *dp = dccp_sk(sk); return dp->dccps_timestamp_echo != 0 || #ifdef CONFIG_IP_DCCP_ACKVEC - (dp->dccps_options.dccpo_send_ack_vector && + (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || #endif inet_csk_ack_scheduled(sk); diff --git a/net/dccp/diag.c b/net/dccp/diag.c index 3f78c00e382..0f25dc39596 100644 --- a/net/dccp/diag.c +++ b/net/dccp/diag.c @@ -30,7 +30,7 @@ static void dccp_get_info(struct sock *sk, struct tcp_info *info) info->tcpi_backoff = icsk->icsk_backoff; info->tcpi_pmtu = icsk->icsk_pmtu_cookie; - if (dp->dccps_options.dccpo_send_ack_vector) + if (dccp_msk(sk)->dccpms_send_ack_vector) info->tcpi_options |= TCPI_OPT_SACK; ccid_hc_rx_get_info(dp->dccps_hc_rx_ccid, sk, info); diff --git a/net/dccp/feat.c b/net/dccp/feat.c index ed0851fa3cb..b09064c4643 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -22,7 +22,7 @@ int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, gfp_t gfp) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt; dccp_pr_debug("feat change type=%d feat=%d\n", type, feature); @@ -30,8 +30,7 @@ int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, /* XXX sanity check feat change request */ /* check if that feature is already being negotiated */ - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { /* ok we found a negotiation for this option already */ if (opt->dccpop_feat == feature && opt->dccpop_type == type) { dccp_pr_debug("Replacing old\n"); @@ -59,7 +58,7 @@ int dccp_feat_change(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len, BUG_ON(opt->dccpop_val == NULL); - list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_pending); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_pending); return 0; } @@ -68,10 +67,10 @@ EXPORT_SYMBOL_GPL(dccp_feat_change); static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); /* figure out if we are changing our CCID or the peer's */ const int rx = type == DCCPO_CHANGE_R; - const u8 ccid_nr = rx ? dp->dccps_options.dccpo_rx_ccid : - dp->dccps_options.dccpo_tx_ccid; + const u8 ccid_nr = rx ? dmsk->dccpms_rx_ccid : dmsk->dccpms_tx_ccid; struct ccid *new_ccid; /* Check if nothing is being changed. */ @@ -85,11 +84,11 @@ static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) if (rx) { ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); dp->dccps_hc_rx_ccid = new_ccid; - dp->dccps_options.dccpo_rx_ccid = new_ccid_nr; + dmsk->dccpms_rx_ccid = new_ccid_nr; } else { ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_tx_ccid = new_ccid; - dp->dccps_options.dccpo_tx_ccid = new_ccid_nr; + dmsk->dccpms_tx_ccid = new_ccid_nr; } return 0; @@ -159,9 +158,9 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, case DCCPF_CCID: /* XXX did i get this right? =P */ if (opt->dccpop_type == DCCPO_CHANGE_L) - res = &dp->dccps_options.dccpo_tx_ccid; + res = &dccp_msk(sk)->dccpms_tx_ccid; else - res = &dp->dccps_options.dccpo_rx_ccid; + res = &dccp_msk(sk)->dccpms_rx_ccid; break; default: @@ -226,7 +225,7 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt, static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt; int rc = 1; u8 t; @@ -242,8 +241,7 @@ static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) t = DCCPO_CHANGE_L; /* find our preference list for this feature */ - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (opt->dccpop_type != t || opt->dccpop_feat != feature) continue; @@ -265,7 +263,7 @@ static int dccp_feat_sp(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) { struct dccp_opt_pend *opt; - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); u8 *copy; int rc; @@ -304,14 +302,14 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len) } dccp_pr_debug("Confirming NN feature %d (val=%d)\n", feature, *copy); - list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); return 0; } static void dccp_feat_empty_confirm(struct sock *sk, u8 type, u8 feature) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); /* XXX check if other confirms for that are queued and recycle slot */ struct dccp_opt_pend *opt = kzalloc(sizeof(*opt), GFP_ATOMIC); @@ -330,20 +328,19 @@ static void dccp_feat_empty_confirm(struct sock *sk, u8 type, u8 feature) /* change feature */ dccp_pr_debug("Empty confirm feature %d type %d\n", feature, type); - list_add_tail(&opt->dccpop_node, &dp->dccps_options.dccpo_conf); + list_add_tail(&opt->dccpop_node, &dmsk->dccpms_conf); } static void dccp_feat_flush_confirm(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); /* Check if there is anything to confirm in the first place */ - int yes = !list_empty(&dp->dccps_options.dccpo_conf); + int yes = !list_empty(&dmsk->dccpms_conf); if (!yes) { struct dccp_opt_pend *opt; - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (opt->dccpop_conf) { yes = 1; break; @@ -407,7 +404,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, { u8 t; struct dccp_opt_pend *opt; - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); int rc = 1; int all_confirmed = 1; @@ -418,8 +415,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, /* locate our change request */ t = type == DCCPO_CONFIRM_L ? DCCPO_CHANGE_R : DCCPO_CHANGE_L; - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { if (!opt->dccpop_conf && opt->dccpop_type == t && opt->dccpop_feat == feature) { /* we found it */ @@ -462,10 +458,10 @@ EXPORT_SYMBOL_GPL(dccp_feat_confirm_recv); void dccp_feat_clean(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt, *next; - list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_pending, + list_for_each_entry_safe(opt, next, &dmsk->dccpms_pending, dccpop_node) { BUG_ON(opt->dccpop_val == NULL); kfree(opt->dccpop_val); @@ -478,16 +474,15 @@ void dccp_feat_clean(struct sock *sk) kfree(opt); } - INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); + INIT_LIST_HEAD(&dmsk->dccpms_pending); - list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, - dccpop_node) { + list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { BUG_ON(opt == NULL); if (opt->dccpop_val != NULL) kfree(opt->dccpop_val); kfree(opt); } - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_conf); } EXPORT_SYMBOL_GPL(dccp_feat_clean); @@ -498,16 +493,15 @@ EXPORT_SYMBOL_GPL(dccp_feat_clean); */ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) { - struct dccp_sock *olddp = dccp_sk(oldsk); - struct dccp_sock *newdp = dccp_sk(newsk); + struct dccp_minisock *olddmsk = dccp_msk(oldsk); + struct dccp_minisock *newdmsk = dccp_msk(newsk); struct dccp_opt_pend *opt; int rc = 0; - INIT_LIST_HEAD(&newdp->dccps_options.dccpo_pending); - INIT_LIST_HEAD(&newdp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&newdmsk->dccpms_pending); + INIT_LIST_HEAD(&newdmsk->dccpms_conf); - list_for_each_entry(opt, &olddp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &olddmsk->dccpms_pending, dccpop_node) { struct dccp_opt_pend *newopt; /* copy the value of the option */ u8 *val = kmalloc(opt->dccpop_len, GFP_ATOMIC); @@ -525,8 +519,7 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk) /* insert the option */ memcpy(newopt, opt, sizeof(*newopt)); newopt->dccpop_val = val; - list_add_tail(&newopt->dccpop_node, - &newdp->dccps_options.dccpo_pending); + list_add_tail(&newopt->dccpop_node, &newdmsk->dccpms_pending); /* XXX what happens with backlogs and multiple connections at * once... @@ -567,27 +560,27 @@ static int __dccp_feat_init(struct sock *sk, u8 type, u8 feat, u8 *val, u8 len) int dccp_feat_init(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); int rc; - INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_pending); + INIT_LIST_HEAD(&dmsk->dccpms_conf); /* CCID L */ rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_CCID, - &dp->dccps_options.dccpo_tx_ccid, 1); + &dmsk->dccpms_tx_ccid, 1); if (rc) goto out; /* CCID R */ rc = __dccp_feat_init(sk, DCCPO_CHANGE_R, DCCPF_CCID, - &dp->dccps_options.dccpo_rx_ccid, 1); + &dmsk->dccpms_rx_ccid, 1); if (rc) goto out; /* Ack ratio */ rc = __dccp_feat_init(sk, DCCPO_CHANGE_L, DCCPF_ACK_RATIO, - &dp->dccps_options.dccpo_ack_ratio, 1); + &dmsk->dccpms_ack_ratio, 1); out: return rc; } diff --git a/net/dccp/input.c b/net/dccp/input.c index f53e3fc7726..bfc53665516 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -60,7 +60,7 @@ static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); - if (dp->dccps_options.dccpo_send_ack_vector) + if (dccp_msk(sk)->dccpms_send_ack_vector) dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_ack_seq); } @@ -246,7 +246,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) @@ -302,7 +302,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, if (dccp_parse_options(sk, skb)) goto out_invalid_packet; - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) @@ -486,7 +486,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKVEC_STATE_RECEIVED)) diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 5324fcacb34..c0349e5b055 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -107,6 +107,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, const struct dccp_request_sock *dreq = dccp_rsk(req); struct inet_connection_sock *newicsk = inet_csk(sk); struct dccp_sock *newdp = dccp_sk(newsk); + struct dccp_minisock *newdmsk = dccp_msk(newsk); newdp->dccps_role = DCCP_ROLE_SERVER; newdp->dccps_hc_rx_ackvec = NULL; @@ -118,7 +119,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, if (dccp_feat_clone(sk, newsk)) goto out_free; - if (newdp->dccps_options.dccpo_send_ack_vector) { + if (newdmsk->dccpms_send_ack_vector) { newdp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_ATOMIC); if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) @@ -126,10 +127,10 @@ struct sock *dccp_create_openreq_child(struct sock *sk, } newdp->dccps_hc_rx_ccid = - ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid, + ccid_hc_rx_new(newdmsk->dccpms_rx_ccid, newsk, GFP_ATOMIC); newdp->dccps_hc_tx_ccid = - ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid, + ccid_hc_tx_new(newdmsk->dccpms_tx_ccid, newsk, GFP_ATOMIC); if (unlikely(newdp->dccps_hc_rx_ccid == NULL || newdp->dccps_hc_tx_ccid == NULL)) { @@ -153,7 +154,7 @@ out_free: */ /* See dccp_v4_conn_request */ - newdp->dccps_options.dccpo_sequence_window = req->rcv_wnd; + newdmsk->dccpms_sequence_window = req->rcv_wnd; newdp->dccps_gar = newdp->dccps_isr = dreq->dreq_isr; dccp_update_gsr(newsk, dreq->dreq_isr); diff --git a/net/dccp/options.c b/net/dccp/options.c index 6e85550cc6f..e9feb2a0c77 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -30,14 +30,14 @@ int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO; int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR; int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT; -void dccp_options_init(struct dccp_options *dccpo) +void dccp_minisock_init(struct dccp_minisock *dmsk) { - dccpo->dccpo_sequence_window = dccp_feat_default_sequence_window; - dccpo->dccpo_rx_ccid = dccp_feat_default_rx_ccid; - dccpo->dccpo_tx_ccid = dccp_feat_default_tx_ccid; - dccpo->dccpo_ack_ratio = dccp_feat_default_ack_ratio; - dccpo->dccpo_send_ack_vector = dccp_feat_default_send_ack_vector; - dccpo->dccpo_send_ndp_count = dccp_feat_default_send_ndp_count; + dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window; + dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid; + dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid; + dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio; + dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector; + dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count; } static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) @@ -151,7 +151,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (pkt_type == DCCP_PKT_DATA) break; - if (dp->dccps_options.dccpo_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_parse(sk, skb, opt, value, len)) goto out_invalid_option; break; @@ -472,12 +472,12 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct dccp_opt_pend *opt, *next; int change = 0; /* confirm any options [NN opts] */ - list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf, - dccpop_node) { + list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { dccp_insert_feat_opt(skb, opt->dccpop_type, opt->dccpop_feat, opt->dccpop_val, opt->dccpop_len); @@ -486,11 +486,10 @@ static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) kfree(opt->dccpop_val); kfree(opt); } - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_conf); /* see which features we need to send */ - list_for_each_entry(opt, &dp->dccps_options.dccpo_pending, - dccpop_node) { + list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { /* see if we need to send any confirm */ if (opt->dccpop_sc) { dccp_insert_feat_opt(skb, opt->dccpop_type + 1, @@ -536,15 +535,16 @@ static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) int dccp_insert_options(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); DCCP_SKB_CB(skb)->dccpd_opt_len = 0; - if (dp->dccps_options.dccpo_send_ndp_count && + if (dmsk->dccpms_send_ndp_count && dccp_insert_option_ndp(sk, skb)) return -1; if (!dccp_packet_without_ack(skb)) { - if (dp->dccps_options.dccpo_send_ack_vector && + if (dmsk->dccpms_send_ack_vector && dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) && dccp_insert_option_ackvec(sk, skb)) return -1; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 8a6d0a83047..ede96907496 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -166,9 +166,10 @@ EXPORT_SYMBOL_GPL(dccp_unhash); int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_minisock *dmsk = dccp_msk(sk); struct inet_connection_sock *icsk = inet_csk(sk); - dccp_options_init(&dp->dccps_options); + dccp_minisock_init(&dp->dccps_minisock); do_gettimeofday(&dp->dccps_epoch); /* @@ -184,22 +185,20 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) if (rc) return rc; - if (dp->dccps_options.dccpo_send_ack_vector) { + if (dmsk->dccpms_send_ack_vector) { dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); if (dp->dccps_hc_rx_ackvec == NULL) return -ENOMEM; } - dp->dccps_hc_rx_ccid = - ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid, - sk, GFP_KERNEL); - dp->dccps_hc_tx_ccid = - ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid, - sk, GFP_KERNEL); + dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid, + sk, GFP_KERNEL); + dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid, + sk, GFP_KERNEL); if (unlikely(dp->dccps_hc_rx_ccid == NULL || dp->dccps_hc_tx_ccid == NULL)) { ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); - if (dp->dccps_options.dccpo_send_ack_vector) { + if (dmsk->dccpms_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; } @@ -208,8 +207,8 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) } } else { /* control socket doesn't need feat nego */ - INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending); - INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf); + INIT_LIST_HEAD(&dmsk->dccpms_pending); + INIT_LIST_HEAD(&dmsk->dccpms_conf); } dccp_init_xmit_timers(sk); @@ -247,7 +246,7 @@ int dccp_destroy_sock(struct sock *sk) kfree(dp->dccps_service_list); dp->dccps_service_list = NULL; - if (dp->dccps_options.dccpo_send_ack_vector) { + if (dccp_msk(sk)->dccpms_send_ack_vector) { dccp_ackvec_free(dp->dccps_hc_rx_ackvec); dp->dccps_hc_rx_ackvec = NULL; } -- cgit v1.2.3-70-g09d2