aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-05 02:14:15 -0400
committerLen Brown <len.brown@intel.com>2009-04-05 02:14:15 -0400
commit478c6a43fcbc6c11609f8cee7c7b57223907754f (patch)
treea7f7952099da60d33032aed6de9c0c56c9f8779e /net/dccp
parent8a3f257c704e02aee9869decd069a806b45be3f1 (diff)
parent6bb597507f9839b13498781e481f5458aea33620 (diff)
Merge branch 'linus' into release
Conflicts: arch/x86/kernel/cpu/cpufreq/longhaul.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ackvec.h3
-rw-r--r--net/dccp/dccp.h26
-rw-r--r--net/dccp/feat.c232
-rw-r--r--net/dccp/feat.h21
-rw-r--r--net/dccp/minisocks.c11
-rw-r--r--net/dccp/options.c8
-rw-r--r--net/dccp/output.c37
-rw-r--r--net/dccp/proto.c2
-rw-r--r--net/dccp/sysctl.c43
9 files changed, 261 insertions, 122 deletions
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index 45f95e55f873..7ea557b7c6b1 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -20,6 +20,9 @@
20/* We can spread an ack vector across multiple options */ 20/* We can spread an ack vector across multiple options */
21#define DCCP_MAX_ACKVEC_LEN (DCCP_SINGLE_OPT_MAXLEN * 2) 21#define DCCP_MAX_ACKVEC_LEN (DCCP_SINGLE_OPT_MAXLEN * 2)
22 22
23/* Estimated minimum average Ack Vector length - used for updating MPS */
24#define DCCPAV_MIN_OPTLEN 16
25
23#define DCCP_ACKVEC_STATE_RECEIVED 0 26#define DCCP_ACKVEC_STATE_RECEIVED 0
24#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) 27#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6)
25#define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6) 28#define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6)
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index f2230fc168e1..d6bc47363b1c 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -42,9 +42,11 @@
42extern int dccp_debug; 42extern int dccp_debug;
43#define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a) 43#define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a)
44#define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a) 44#define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a)
45#define dccp_debug(fmt, a...) dccp_pr_debug_cat(KERN_DEBUG fmt, ##a)
45#else 46#else
46#define dccp_pr_debug(format, a...) 47#define dccp_pr_debug(format, a...)
47#define dccp_pr_debug_cat(format, a...) 48#define dccp_pr_debug_cat(format, a...)
49#define dccp_debug(format, a...)
48#endif 50#endif
49 51
50extern struct inet_hashinfo dccp_hashinfo; 52extern struct inet_hashinfo dccp_hashinfo;
@@ -61,11 +63,14 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
61 * - DCCP-Reset with ACK Subheader and 4 bytes of Reset Code fields 63 * - DCCP-Reset with ACK Subheader and 4 bytes of Reset Code fields
62 * Hence a safe upper bound for the maximum option length is 1020-28 = 992 64 * Hence a safe upper bound for the maximum option length is 1020-28 = 992
63 */ 65 */
64#define MAX_DCCP_SPECIFIC_HEADER (255 * sizeof(int)) 66#define MAX_DCCP_SPECIFIC_HEADER (255 * sizeof(uint32_t))
65#define DCCP_MAX_PACKET_HDR 28 67#define DCCP_MAX_PACKET_HDR 28
66#define DCCP_MAX_OPT_LEN (MAX_DCCP_SPECIFIC_HEADER - DCCP_MAX_PACKET_HDR) 68#define DCCP_MAX_OPT_LEN (MAX_DCCP_SPECIFIC_HEADER - DCCP_MAX_PACKET_HDR)
67#define MAX_DCCP_HEADER (MAX_DCCP_SPECIFIC_HEADER + MAX_HEADER) 69#define MAX_DCCP_HEADER (MAX_DCCP_SPECIFIC_HEADER + MAX_HEADER)
68 70
71/* Upper bound for initial feature-negotiation overhead (padded to 32 bits) */
72#define DCCP_FEATNEG_OVERHEAD (32 * sizeof(uint32_t))
73
69#define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT 74#define DCCP_TIMEWAIT_LEN (60 * HZ) /* how long to wait to destroy TIME-WAIT
70 * state, about 60 seconds */ 75 * state, about 60 seconds */
71 76
@@ -95,9 +100,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
95extern int sysctl_dccp_request_retries; 100extern int sysctl_dccp_request_retries;
96extern int sysctl_dccp_retries1; 101extern int sysctl_dccp_retries1;
97extern int sysctl_dccp_retries2; 102extern int sysctl_dccp_retries2;
98extern int sysctl_dccp_feat_sequence_window;
99extern int sysctl_dccp_feat_rx_ccid;
100extern int sysctl_dccp_feat_tx_ccid;
101extern int sysctl_dccp_tx_qlen; 103extern int sysctl_dccp_tx_qlen;
102extern int sysctl_dccp_sync_ratelimit; 104extern int sysctl_dccp_sync_ratelimit;
103 105
@@ -409,23 +411,21 @@ static inline void dccp_hdr_set_ack(struct dccp_hdr_ack_bits *dhack,
409static inline void dccp_update_gsr(struct sock *sk, u64 seq) 411static inline void dccp_update_gsr(struct sock *sk, u64 seq)
410{ 412{
411 struct dccp_sock *dp = dccp_sk(sk); 413 struct dccp_sock *dp = dccp_sk(sk);
412 const struct dccp_minisock *dmsk = dccp_msk(sk);
413 414
414 dp->dccps_gsr = seq; 415 dp->dccps_gsr = seq;
415 dccp_set_seqno(&dp->dccps_swl, 416 /* Sequence validity window depends on remote Sequence Window (7.5.1) */
416 dp->dccps_gsr + 1 - (dmsk->dccpms_sequence_window / 4)); 417 dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);
417 dccp_set_seqno(&dp->dccps_swh, 418 dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4);
418 dp->dccps_gsr + (3 * dmsk->dccpms_sequence_window) / 4);
419} 419}
420 420
421static inline void dccp_update_gss(struct sock *sk, u64 seq) 421static inline void dccp_update_gss(struct sock *sk, u64 seq)
422{ 422{
423 struct dccp_sock *dp = dccp_sk(sk); 423 struct dccp_sock *dp = dccp_sk(sk);
424 424
425 dp->dccps_awh = dp->dccps_gss = seq; 425 dp->dccps_gss = seq;
426 dccp_set_seqno(&dp->dccps_awl, 426 /* Ack validity window depends on local Sequence Window value (7.5.1) */
427 (dp->dccps_gss - 427 dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win);
428 dccp_msk(sk)->dccpms_sequence_window + 1)); 428 dp->dccps_awh = dp->dccps_gss;
429} 429}
430 430
431static inline int dccp_ack_pending(const struct sock *sk) 431static inline int dccp_ack_pending(const struct sock *sk)
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 4152308958ab..b04160a2eea5 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -25,6 +25,11 @@
25#include "ccid.h" 25#include "ccid.h"
26#include "feat.h" 26#include "feat.h"
27 27
28/* feature-specific sysctls - initialised to the defaults from RFC 4340, 6.4 */
29unsigned long sysctl_dccp_sequence_window __read_mostly = 100;
30int sysctl_dccp_rx_ccid __read_mostly = 2,
31 sysctl_dccp_tx_ccid __read_mostly = 2;
32
28/* 33/*
29 * Feature activation handlers. 34 * Feature activation handlers.
30 * 35 *
@@ -51,8 +56,17 @@ static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)
51 56
52static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx) 57static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx)
53{ 58{
54 if (!rx) 59 struct dccp_sock *dp = dccp_sk(sk);
55 dccp_msk(sk)->dccpms_sequence_window = seq_win; 60
61 if (rx) {
62 dp->dccps_r_seq_win = seq_win;
63 /* propagate changes to update SWL/SWH */
64 dccp_update_gsr(sk, dp->dccps_gsr);
65 } else {
66 dp->dccps_l_seq_win = seq_win;
67 /* propagate changes to update AWL */
68 dccp_update_gss(sk, dp->dccps_gss);
69 }
56 return 0; 70 return 0;
57} 71}
58 72
@@ -194,6 +208,100 @@ static int dccp_feat_default_value(u8 feat_num)
194 return idx < 0 ? 0 : dccp_feat_table[idx].default_value; 208 return idx < 0 ? 0 : dccp_feat_table[idx].default_value;
195} 209}
196 210
211/*
212 * Debugging and verbose-printing section
213 */
214static const char *dccp_feat_fname(const u8 feat)
215{
216 static const char *feature_names[] = {
217 [DCCPF_RESERVED] = "Reserved",
218 [DCCPF_CCID] = "CCID",
219 [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos",
220 [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
221 [DCCPF_ECN_INCAPABLE] = "ECN Incapable",
222 [DCCPF_ACK_RATIO] = "Ack Ratio",
223 [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
224 [DCCPF_SEND_NDP_COUNT] = "Send NDP Count",
225 [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage",
226 [DCCPF_DATA_CHECKSUM] = "Send Data Checksum",
227 };
228 if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)
229 return feature_names[DCCPF_RESERVED];
230
231 if (feat == DCCPF_SEND_LEV_RATE)
232 return "Send Loss Event Rate";
233 if (feat >= DCCPF_MIN_CCID_SPECIFIC)
234 return "CCID-specific";
235
236 return feature_names[feat];
237}
238
239static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING",
240 "UNSTABLE", "STABLE" };
241
242#ifdef CONFIG_IP_DCCP_DEBUG
243static const char *dccp_feat_oname(const u8 opt)
244{
245 switch (opt) {
246 case DCCPO_CHANGE_L: return "Change_L";
247 case DCCPO_CONFIRM_L: return "Confirm_L";
248 case DCCPO_CHANGE_R: return "Change_R";
249 case DCCPO_CONFIRM_R: return "Confirm_R";
250 }
251 return NULL;
252}
253
254static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val)
255{
256 u8 i, type = dccp_feat_type(feat_num);
257
258 if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL))
259 dccp_pr_debug_cat("(NULL)");
260 else if (type == FEAT_SP)
261 for (i = 0; i < val->sp.len; i++)
262 dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]);
263 else if (type == FEAT_NN)
264 dccp_pr_debug_cat("%llu", (unsigned long long)val->nn);
265 else
266 dccp_pr_debug_cat("unknown type %u", type);
267}
268
269static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len)
270{
271 u8 type = dccp_feat_type(feat_num);
272 dccp_feat_val fval = { .sp.vec = list, .sp.len = len };
273
274 if (type == FEAT_NN)
275 fval.nn = dccp_decode_value_var(list, len);
276 dccp_feat_printval(feat_num, &fval);
277}
278
279static void dccp_feat_print_entry(struct dccp_feat_entry const *entry)
280{
281 dccp_debug(" * %s %s = ", entry->is_local ? "local" : "remote",
282 dccp_feat_fname(entry->feat_num));
283 dccp_feat_printval(entry->feat_num, &entry->val);
284 dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state],
285 entry->needs_confirm ? "(Confirm pending)" : "");
286}
287
288#define dccp_feat_print_opt(opt, feat, val, len, mandatory) do { \
289 dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\
290 dccp_feat_printvals(feat, val, len); \
291 dccp_pr_debug_cat(") %s\n", mandatory ? "!" : ""); } while (0)
292
293#define dccp_feat_print_fnlist(fn_list) { \
294 const struct dccp_feat_entry *___entry; \
295 \
296 dccp_pr_debug("List Dump:\n"); \
297 list_for_each_entry(___entry, fn_list, node) \
298 dccp_feat_print_entry(___entry); \
299}
300#else /* ! CONFIG_IP_DCCP_DEBUG */
301#define dccp_feat_print_opt(opt, feat, val, len, mandatory)
302#define dccp_feat_print_fnlist(fn_list)
303#endif
304
197static int __dccp_feat_activate(struct sock *sk, const int idx, 305static int __dccp_feat_activate(struct sock *sk, const int idx,
198 const bool is_local, dccp_feat_val const *fval) 306 const bool is_local, dccp_feat_val const *fval)
199{ 307{
@@ -226,6 +334,10 @@ static int __dccp_feat_activate(struct sock *sk, const int idx,
226 /* Location is RX if this is a local-RX or remote-TX feature */ 334 /* Location is RX if this is a local-RX or remote-TX feature */
227 rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); 335 rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX));
228 336
337 dccp_debug(" -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX",
338 dccp_feat_fname(dccp_feat_table[idx].feat_num),
339 fval ? "" : "default ", (unsigned long long)val);
340
229 return dccp_feat_table[idx].activation_hdlr(sk, val, rx); 341 return dccp_feat_table[idx].activation_hdlr(sk, val, rx);
230} 342}
231 343
@@ -530,6 +642,7 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,
530 return -1; 642 return -1;
531 } 643 }
532 } 644 }
645 dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0);
533 646
534 if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) 647 if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt))
535 return -1; 648 return -1;
@@ -783,6 +896,7 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp)
783 while (i--) 896 while (i--)
784 if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) 897 if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i))
785 return -1; 898 return -1;
899 dccp_feat_print_fnlist(fn);
786 return 0; 900 return 0;
787} 901}
788 902
@@ -901,6 +1015,8 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
901 if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ 1015 if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */
902 goto unknown_feature_or_value; 1016 goto unknown_feature_or_value;
903 1017
1018 dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
1019
904 /* 1020 /*
905 * Negotiation of NN features: Change R is invalid, so there is no 1021 * Negotiation of NN features: Change R is invalid, so there is no
906 * simultaneous negotiation; hence we do not look up in the list. 1022 * simultaneous negotiation; hence we do not look up in the list.
@@ -1006,6 +1122,8 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
1006 const bool local = (opt == DCCPO_CONFIRM_R); 1122 const bool local = (opt == DCCPO_CONFIRM_R);
1007 struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); 1123 struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local);
1008 1124
1125 dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
1126
1009 if (entry == NULL) { /* nothing queued: ignore or handle error */ 1127 if (entry == NULL) { /* nothing queued: ignore or handle error */
1010 if (is_mandatory && type == FEAT_UNKNOWN) 1128 if (is_mandatory && type == FEAT_UNKNOWN)
1011 return DCCP_RESET_CODE_MANDATORY_ERROR; 1129 return DCCP_RESET_CODE_MANDATORY_ERROR;
@@ -1115,23 +1233,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1115 return 0; /* ignore FN options in all other states */ 1233 return 0; /* ignore FN options in all other states */
1116} 1234}
1117 1235
1236/**
1237 * dccp_feat_init - Seed feature negotiation with host-specific defaults
1238 * This initialises global defaults, depending on the value of the sysctls.
1239 * These can later be overridden by registering changes via setsockopt calls.
1240 * The last link in the chain is finalise_settings, to make sure that between
1241 * here and the start of actual feature negotiation no inconsistencies enter.
1242 *
1243 * All features not appearing below use either defaults or are otherwise
1244 * later adjusted through dccp_feat_finalise_settings().
1245 */
1118int dccp_feat_init(struct sock *sk) 1246int dccp_feat_init(struct sock *sk)
1119{ 1247{
1120 struct dccp_sock *dp = dccp_sk(sk); 1248 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
1121 struct dccp_minisock *dmsk = dccp_msk(sk); 1249 u8 on = 1, off = 0;
1122 int rc; 1250 int rc;
1251 struct {
1252 u8 *val;
1253 u8 len;
1254 } tx, rx;
1255
1256 /* Non-negotiable (NN) features */
1257 rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,
1258 sysctl_dccp_sequence_window);
1259 if (rc)
1260 return rc;
1261
1262 /* Server-priority (SP) features */
1263
1264 /* Advertise that short seqnos are not supported (7.6.1) */
1265 rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);
1266 if (rc)
1267 return rc;
1123 1268
1124 INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ 1269 /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */
1125 INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ 1270 rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);
1271 if (rc)
1272 return rc;
1273
1274 /*
1275 * We advertise the available list of CCIDs and reorder according to
1276 * preferences, to avoid failure resulting from negotiating different
1277 * singleton values (which always leads to failure).
1278 * These settings can still (later) be overridden via sockopts.
1279 */
1280 if (ccid_get_builtin_ccids(&tx.val, &tx.len) ||
1281 ccid_get_builtin_ccids(&rx.val, &rx.len))
1282 return -ENOBUFS;
1283
1284 if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) ||
1285 !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len))
1286 goto free_ccid_lists;
1287
1288 rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);
1289 if (rc)
1290 goto free_ccid_lists;
1291
1292 rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);
1126 1293
1127 /* Ack ratio */ 1294free_ccid_lists:
1128 rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, 1295 kfree(tx.val);
1129 dp->dccps_l_ack_ratio); 1296 kfree(rx.val);
1130 return rc; 1297 return rc;
1131} 1298}
1132 1299
1133EXPORT_SYMBOL_GPL(dccp_feat_init);
1134
1135int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) 1300int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
1136{ 1301{
1137 struct dccp_sock *dp = dccp_sk(sk); 1302 struct dccp_sock *dp = dccp_sk(sk);
@@ -1156,9 +1321,10 @@ int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
1156 goto activation_failed; 1321 goto activation_failed;
1157 } 1322 }
1158 if (cur->state != FEAT_STABLE) { 1323 if (cur->state != FEAT_STABLE) {
1159 DCCP_CRIT("Negotiation of %s %u failed in state %u", 1324 DCCP_CRIT("Negotiation of %s %s failed in state %s",
1160 cur->is_local ? "local" : "remote", 1325 cur->is_local ? "local" : "remote",
1161 cur->feat_num, cur->state); 1326 dccp_feat_fname(cur->feat_num),
1327 dccp_feat_sname[cur->state]);
1162 goto activation_failed; 1328 goto activation_failed;
1163 } 1329 }
1164 fvals[idx][cur->is_local] = &cur->val; 1330 fvals[idx][cur->is_local] = &cur->val;
@@ -1199,43 +1365,3 @@ activation_failed:
1199 dp->dccps_hc_rx_ackvec = NULL; 1365 dp->dccps_hc_rx_ackvec = NULL;
1200 return -1; 1366 return -1;
1201} 1367}
1202
1203#ifdef CONFIG_IP_DCCP_DEBUG
1204const char *dccp_feat_typename(const u8 type)
1205{
1206 switch(type) {
1207 case DCCPO_CHANGE_L: return("ChangeL");
1208 case DCCPO_CONFIRM_L: return("ConfirmL");
1209 case DCCPO_CHANGE_R: return("ChangeR");
1210 case DCCPO_CONFIRM_R: return("ConfirmR");
1211 /* the following case must not appear in feature negotation */
1212 default: dccp_pr_debug("unknown type %d [BUG!]\n", type);
1213 }
1214 return NULL;
1215}
1216
1217const char *dccp_feat_name(const u8 feat)
1218{
1219 static const char *feature_names[] = {
1220 [DCCPF_RESERVED] = "Reserved",
1221 [DCCPF_CCID] = "CCID",
1222 [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos",
1223 [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
1224 [DCCPF_ECN_INCAPABLE] = "ECN Incapable",
1225 [DCCPF_ACK_RATIO] = "Ack Ratio",
1226 [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
1227 [DCCPF_SEND_NDP_COUNT] = "Send NDP Count",
1228 [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage",
1229 [DCCPF_DATA_CHECKSUM] = "Send Data Checksum",
1230 };
1231 if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)
1232 return feature_names[DCCPF_RESERVED];
1233
1234 if (feat == DCCPF_SEND_LEV_RATE)
1235 return "Send Loss Event Rate";
1236 if (feat >= DCCPF_MIN_CCID_SPECIFIC)
1237 return "CCID-specific";
1238
1239 return feature_names[feat];
1240}
1241#endif /* CONFIG_IP_DCCP_DEBUG */
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index 9b46e2a7866e..f96721619def 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -100,26 +100,21 @@ struct ccid_dependency {
100 u8 val; 100 u8 val;
101}; 101};
102 102
103#ifdef CONFIG_IP_DCCP_DEBUG 103/*
104extern const char *dccp_feat_typename(const u8 type); 104 * Sysctls to seed defaults for feature negotiation
105extern const char *dccp_feat_name(const u8 feat); 105 */
106 106extern unsigned long sysctl_dccp_sequence_window;
107static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val) 107extern int sysctl_dccp_rx_ccid;
108{ 108extern int sysctl_dccp_tx_ccid;
109 dccp_pr_debug("%s(%s (%d), %d)\n", dccp_feat_typename(type),
110 dccp_feat_name(feat), feat, val);
111}
112#else
113#define dccp_feat_debug(type, feat, val)
114#endif /* CONFIG_IP_DCCP_DEBUG */
115 109
110extern int dccp_feat_init(struct sock *sk);
111extern void dccp_feat_initialise_sysctls(void);
116extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, 112extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
117 u8 const *list, u8 len); 113 u8 const *list, u8 len);
118extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val); 114extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);
119extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *, 115extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *,
120 u8 mand, u8 opt, u8 feat, u8 *val, u8 len); 116 u8 mand, u8 opt, u8 feat, u8 *val, u8 len);
121extern int dccp_feat_clone_list(struct list_head const *, struct list_head *); 117extern int dccp_feat_clone_list(struct list_head const *, struct list_head *);
122extern int dccp_feat_init(struct sock *sk);
123 118
124/* 119/*
125 * Encoding variable-length options and their maximum length. 120 * Encoding variable-length options and their maximum length.
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 6821ae33dd37..5ca49cec95f5 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -42,11 +42,6 @@ struct inet_timewait_death_row dccp_death_row = {
42 42
43EXPORT_SYMBOL_GPL(dccp_death_row); 43EXPORT_SYMBOL_GPL(dccp_death_row);
44 44
45void dccp_minisock_init(struct dccp_minisock *dmsk)
46{
47 dmsk->dccpms_sequence_window = sysctl_dccp_feat_sequence_window;
48}
49
50void dccp_time_wait(struct sock *sk, int state, int timeo) 45void dccp_time_wait(struct sock *sk, int state, int timeo)
51{ 46{
52 struct inet_timewait_sock *tw = NULL; 47 struct inet_timewait_sock *tw = NULL;
@@ -110,7 +105,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
110 struct dccp_request_sock *dreq = dccp_rsk(req); 105 struct dccp_request_sock *dreq = dccp_rsk(req);
111 struct inet_connection_sock *newicsk = inet_csk(newsk); 106 struct inet_connection_sock *newicsk = inet_csk(newsk);
112 struct dccp_sock *newdp = dccp_sk(newsk); 107 struct dccp_sock *newdp = dccp_sk(newsk);
113 struct dccp_minisock *newdmsk = dccp_msk(newsk);
114 108
115 newdp->dccps_role = DCCP_ROLE_SERVER; 109 newdp->dccps_role = DCCP_ROLE_SERVER;
116 newdp->dccps_hc_rx_ackvec = NULL; 110 newdp->dccps_hc_rx_ackvec = NULL;
@@ -128,10 +122,6 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
128 * Initialize S.GAR := S.ISS 122 * Initialize S.GAR := S.ISS
129 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies 123 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
130 */ 124 */
131
132 /* See dccp_v4_conn_request */
133 newdmsk->dccpms_sequence_window = req->rcv_wnd;
134
135 newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss; 125 newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss;
136 dccp_update_gss(newsk, dreq->dreq_iss); 126 dccp_update_gss(newsk, dreq->dreq_iss);
137 127
@@ -290,7 +280,6 @@ int dccp_reqsk_init(struct request_sock *req,
290 inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport; 280 inet_rsk(req)->rmt_port = dccp_hdr(skb)->dccph_sport;
291 inet_rsk(req)->loc_port = dccp_hdr(skb)->dccph_dport; 281 inet_rsk(req)->loc_port = dccp_hdr(skb)->dccph_dport;
292 inet_rsk(req)->acked = 0; 282 inet_rsk(req)->acked = 0;
293 req->rcv_wnd = sysctl_dccp_feat_sequence_window;
294 dreq->dreq_timestamp_echo = 0; 283 dreq->dreq_timestamp_echo = 0;
295 284
296 /* inherit feature negotiation options from listening socket */ 285 /* inherit feature negotiation options from listening socket */
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 7b1165c21f51..1b08cae9c65b 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -23,10 +23,6 @@
23#include "dccp.h" 23#include "dccp.h"
24#include "feat.h" 24#include "feat.h"
25 25
26int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
27int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID;
28int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID;
29
30u64 dccp_decode_value_var(const u8 *bf, const u8 len) 26u64 dccp_decode_value_var(const u8 *bf, const u8 len)
31{ 27{
32 u64 value = 0; 28 u64 value = 0;
@@ -502,10 +498,6 @@ int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
502 *to++ = *val; 498 *to++ = *val;
503 if (len) 499 if (len)
504 memcpy(to, val, len); 500 memcpy(to, val, len);
505
506 dccp_pr_debug("%s(%s (%d), ...), length %d\n",
507 dccp_feat_typename(type),
508 dccp_feat_name(feat), feat, len);
509 return 0; 501 return 0;
510} 502}
511 503
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 22a618af4893..36bcc00654d3 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -161,21 +161,27 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
161 struct inet_connection_sock *icsk = inet_csk(sk); 161 struct inet_connection_sock *icsk = inet_csk(sk);
162 struct dccp_sock *dp = dccp_sk(sk); 162 struct dccp_sock *dp = dccp_sk(sk);
163 u32 ccmps = dccp_determine_ccmps(dp); 163 u32 ccmps = dccp_determine_ccmps(dp);
164 int cur_mps = ccmps ? min(pmtu, ccmps) : pmtu; 164 u32 cur_mps = ccmps ? min(pmtu, ccmps) : pmtu;
165 165
166 /* Account for header lengths and IPv4/v6 option overhead */ 166 /* Account for header lengths and IPv4/v6 option overhead */
167 cur_mps -= (icsk->icsk_af_ops->net_header_len + icsk->icsk_ext_hdr_len + 167 cur_mps -= (icsk->icsk_af_ops->net_header_len + icsk->icsk_ext_hdr_len +
168 sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)); 168 sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
169 169
170 /* 170 /*
171 * FIXME: this should come from the CCID infrastructure, where, say, 171 * Leave enough headroom for common DCCP header options.
172 * TFRC will say it wants TIMESTAMPS, ELAPSED time, etc, for now lets 172 * This only considers options which may appear on DCCP-Data packets, as
173 * put a rough estimate for NDP + TIMESTAMP + TIMESTAMP_ECHO + ELAPSED 173 * per table 3 in RFC 4340, 5.8. When running out of space for other
174 * TIME + TFRC_OPT_LOSS_EVENT_RATE + TFRC_OPT_RECEIVE_RATE + padding to 174 * options (eg. Ack Vector which can take up to 255 bytes), it is better
175 * make it a multiple of 4 175 * to schedule a separate Ack. Thus we leave headroom for the following:
176 * - 1 byte for Slow Receiver (11.6)
177 * - 6 bytes for Timestamp (13.1)
178 * - 10 bytes for Timestamp Echo (13.3)
179 * - 8 bytes for NDP count (7.7, when activated)
180 * - 6 bytes for Data Checksum (9.3)
181 * - %DCCPAV_MIN_OPTLEN bytes for Ack Vector size (11.4, when enabled)
176 */ 182 */
177 183 cur_mps -= roundup(1 + 6 + 10 + dp->dccps_send_ndp_count * 8 + 6 +
178 cur_mps -= roundup(5 + 6 + 10 + 6 + 6 + 6, 4); 184 (dp->dccps_hc_rx_ackvec ? DCCPAV_MIN_OPTLEN : 0), 4);
179 185
180 /* And store cached results */ 186 /* And store cached results */
181 icsk->icsk_pmtu_cookie = pmtu; 187 icsk->icsk_pmtu_cookie = pmtu;
@@ -270,7 +276,20 @@ void dccp_write_xmit(struct sock *sk, int block)
270 const int len = skb->len; 276 const int len = skb->len;
271 277
272 if (sk->sk_state == DCCP_PARTOPEN) { 278 if (sk->sk_state == DCCP_PARTOPEN) {
273 /* See 8.1.5. Handshake Completion */ 279 const u32 cur_mps = dp->dccps_mss_cache - DCCP_FEATNEG_OVERHEAD;
280 /*
281 * See 8.1.5 - Handshake Completion.
282 *
283 * For robustness we resend Confirm options until the client has
284 * entered OPEN. During the initial feature negotiation, the MPS
285 * is smaller than usual, reduced by the Change/Confirm options.
286 */
287 if (!list_empty(&dp->dccps_featneg) && len > cur_mps) {
288 DCCP_WARN("Payload too large (%d) for featneg.\n", len);
289 dccp_send_ack(sk);
290 dccp_feat_list_purge(&dp->dccps_featneg);
291 }
292
274 inet_csk_schedule_ack(sk); 293 inet_csk_schedule_ack(sk);
275 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 294 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
276 inet_csk(sk)->icsk_rto, 295 inet_csk(sk)->icsk_rto,
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 945b4d5d23b3..314a1b5c033c 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -174,8 +174,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
174 struct dccp_sock *dp = dccp_sk(sk); 174 struct dccp_sock *dp = dccp_sk(sk);
175 struct inet_connection_sock *icsk = inet_csk(sk); 175 struct inet_connection_sock *icsk = inet_csk(sk);
176 176
177 dccp_minisock_init(&dp->dccps_minisock);
178
179 icsk->icsk_rto = DCCP_TIMEOUT_INIT; 177 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
180 icsk->icsk_syn_retries = sysctl_dccp_request_retries; 178 icsk->icsk_syn_retries = sysctl_dccp_request_retries;
181 sk->sk_state = DCCP_CLOSED; 179 sk->sk_state = DCCP_CLOSED;
diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c
index 018e210875e1..a5a1856234e7 100644
--- a/net/dccp/sysctl.c
+++ b/net/dccp/sysctl.c
@@ -18,55 +18,72 @@
18#error This file should not be compiled without CONFIG_SYSCTL defined 18#error This file should not be compiled without CONFIG_SYSCTL defined
19#endif 19#endif
20 20
21/* Boundary values */
22static int zero = 0,
23 u8_max = 0xFF;
24static unsigned long seqw_min = 32;
25
21static struct ctl_table dccp_default_table[] = { 26static struct ctl_table dccp_default_table[] = {
22 { 27 {
23 .procname = "seq_window", 28 .procname = "seq_window",
24 .data = &sysctl_dccp_feat_sequence_window, 29 .data = &sysctl_dccp_sequence_window,
25 .maxlen = sizeof(sysctl_dccp_feat_sequence_window), 30 .maxlen = sizeof(sysctl_dccp_sequence_window),
26 .mode = 0644, 31 .mode = 0644,
27 .proc_handler = proc_dointvec, 32 .proc_handler = proc_doulongvec_minmax,
33 .extra1 = &seqw_min, /* RFC 4340, 7.5.2 */
28 }, 34 },
29 { 35 {
30 .procname = "rx_ccid", 36 .procname = "rx_ccid",
31 .data = &sysctl_dccp_feat_rx_ccid, 37 .data = &sysctl_dccp_rx_ccid,
32 .maxlen = sizeof(sysctl_dccp_feat_rx_ccid), 38 .maxlen = sizeof(sysctl_dccp_rx_ccid),
33 .mode = 0644, 39 .mode = 0644,
34 .proc_handler = proc_dointvec, 40 .proc_handler = proc_dointvec_minmax,
41 .extra1 = &zero,
42 .extra2 = &u8_max, /* RFC 4340, 10. */
35 }, 43 },
36 { 44 {
37 .procname = "tx_ccid", 45 .procname = "tx_ccid",
38 .data = &sysctl_dccp_feat_tx_ccid, 46 .data = &sysctl_dccp_tx_ccid,
39 .maxlen = sizeof(sysctl_dccp_feat_tx_ccid), 47 .maxlen = sizeof(sysctl_dccp_tx_ccid),
40 .mode = 0644, 48 .mode = 0644,
41 .proc_handler = proc_dointvec, 49 .proc_handler = proc_dointvec_minmax,
50 .extra1 = &zero,
51 .extra2 = &u8_max, /* RFC 4340, 10. */
42 }, 52 },
43 { 53 {
44 .procname = "request_retries", 54 .procname = "request_retries",
45 .data = &sysctl_dccp_request_retries, 55 .data = &sysctl_dccp_request_retries,
46 .maxlen = sizeof(sysctl_dccp_request_retries), 56 .maxlen = sizeof(sysctl_dccp_request_retries),
47 .mode = 0644, 57 .mode = 0644,
48 .proc_handler = proc_dointvec, 58 .proc_handler = proc_dointvec_minmax,
59 .extra1 = &zero,
60 .extra2 = &u8_max,
49 }, 61 },
50 { 62 {
51 .procname = "retries1", 63 .procname = "retries1",
52 .data = &sysctl_dccp_retries1, 64 .data = &sysctl_dccp_retries1,
53 .maxlen = sizeof(sysctl_dccp_retries1), 65 .maxlen = sizeof(sysctl_dccp_retries1),
54 .mode = 0644, 66 .mode = 0644,
55 .proc_handler = proc_dointvec, 67 .proc_handler = proc_dointvec_minmax,
68 .extra1 = &zero,
69 .extra2 = &u8_max,
56 }, 70 },
57 { 71 {
58 .procname = "retries2", 72 .procname = "retries2",
59 .data = &sysctl_dccp_retries2, 73 .data = &sysctl_dccp_retries2,
60 .maxlen = sizeof(sysctl_dccp_retries2), 74 .maxlen = sizeof(sysctl_dccp_retries2),
61 .mode = 0644, 75 .mode = 0644,
62 .proc_handler = proc_dointvec, 76 .proc_handler = proc_dointvec_minmax,
77 .extra1 = &zero,
78 .extra2 = &u8_max,
63 }, 79 },
64 { 80 {
65 .procname = "tx_qlen", 81 .procname = "tx_qlen",
66 .data = &sysctl_dccp_tx_qlen, 82 .data = &sysctl_dccp_tx_qlen,
67 .maxlen = sizeof(sysctl_dccp_tx_qlen), 83 .maxlen = sizeof(sysctl_dccp_tx_qlen),
68 .mode = 0644, 84 .mode = 0644,
69 .proc_handler = proc_dointvec, 85 .proc_handler = proc_dointvec_minmax,
86 .extra1 = &zero,
70 }, 87 },
71 { 88 {
72 .procname = "sync_ratelimit", 89 .procname = "sync_ratelimit",