aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/feat.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r--net/dccp/feat.c149
1 files changed, 107 insertions, 42 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 12006e9b2472..b04160a2eea5 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -208,6 +208,100 @@ static int dccp_feat_default_value(u8 feat_num)
208 return idx < 0 ? 0 : dccp_feat_table[idx].default_value; 208 return idx < 0 ? 0 : dccp_feat_table[idx].default_value;
209} 209}
210 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
211static int __dccp_feat_activate(struct sock *sk, const int idx, 305static int __dccp_feat_activate(struct sock *sk, const int idx,
212 const bool is_local, dccp_feat_val const *fval) 306 const bool is_local, dccp_feat_val const *fval)
213{ 307{
@@ -240,6 +334,10 @@ static int __dccp_feat_activate(struct sock *sk, const int idx,
240 /* 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 */
241 rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); 335 rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX));
242 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
243 return dccp_feat_table[idx].activation_hdlr(sk, val, rx); 341 return dccp_feat_table[idx].activation_hdlr(sk, val, rx);
244} 342}
245 343
@@ -544,6 +642,7 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,
544 return -1; 642 return -1;
545 } 643 }
546 } 644 }
645 dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0);
547 646
548 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))
549 return -1; 648 return -1;
@@ -797,6 +896,7 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp)
797 while (i--) 896 while (i--)
798 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))
799 return -1; 898 return -1;
899 dccp_feat_print_fnlist(fn);
800 return 0; 900 return 0;
801} 901}
802 902
@@ -915,6 +1015,8 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
915 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 */
916 goto unknown_feature_or_value; 1016 goto unknown_feature_or_value;
917 1017
1018 dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
1019
918 /* 1020 /*
919 * 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
920 * simultaneous negotiation; hence we do not look up in the list. 1022 * simultaneous negotiation; hence we do not look up in the list.
@@ -1020,6 +1122,8 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
1020 const bool local = (opt == DCCPO_CONFIRM_R); 1122 const bool local = (opt == DCCPO_CONFIRM_R);
1021 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);
1022 1124
1125 dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
1126
1023 if (entry == NULL) { /* nothing queued: ignore or handle error */ 1127 if (entry == NULL) { /* nothing queued: ignore or handle error */
1024 if (is_mandatory && type == FEAT_UNKNOWN) 1128 if (is_mandatory && type == FEAT_UNKNOWN)
1025 return DCCP_RESET_CODE_MANDATORY_ERROR; 1129 return DCCP_RESET_CODE_MANDATORY_ERROR;
@@ -1217,9 +1321,10 @@ int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
1217 goto activation_failed; 1321 goto activation_failed;
1218 } 1322 }
1219 if (cur->state != FEAT_STABLE) { 1323 if (cur->state != FEAT_STABLE) {
1220 DCCP_CRIT("Negotiation of %s %u failed in state %u", 1324 DCCP_CRIT("Negotiation of %s %s failed in state %s",
1221 cur->is_local ? "local" : "remote", 1325 cur->is_local ? "local" : "remote",
1222 cur->feat_num, cur->state); 1326 dccp_feat_fname(cur->feat_num),
1327 dccp_feat_sname[cur->state]);
1223 goto activation_failed; 1328 goto activation_failed;
1224 } 1329 }
1225 fvals[idx][cur->is_local] = &cur->val; 1330 fvals[idx][cur->is_local] = &cur->val;
@@ -1260,43 +1365,3 @@ activation_failed:
1260 dp->dccps_hc_rx_ackvec = NULL; 1365 dp->dccps_hc_rx_ackvec = NULL;
1261 return -1; 1366 return -1;
1262} 1367}
1263
1264#ifdef CONFIG_IP_DCCP_DEBUG
1265const char *dccp_feat_typename(const u8 type)
1266{
1267 switch(type) {
1268 case DCCPO_CHANGE_L: return("ChangeL");
1269 case DCCPO_CONFIRM_L: return("ConfirmL");
1270 case DCCPO_CHANGE_R: return("ChangeR");
1271 case DCCPO_CONFIRM_R: return("ConfirmR");
1272 /* the following case must not appear in feature negotation */
1273 default: dccp_pr_debug("unknown type %d [BUG!]\n", type);
1274 }
1275 return NULL;
1276}
1277
1278const char *dccp_feat_name(const u8 feat)
1279{
1280 static const char *feature_names[] = {
1281 [DCCPF_RESERVED] = "Reserved",
1282 [DCCPF_CCID] = "CCID",
1283 [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos",
1284 [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
1285 [DCCPF_ECN_INCAPABLE] = "ECN Incapable",
1286 [DCCPF_ACK_RATIO] = "Ack Ratio",
1287 [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
1288 [DCCPF_SEND_NDP_COUNT] = "Send NDP Count",
1289 [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage",
1290 [DCCPF_DATA_CHECKSUM] = "Send Data Checksum",
1291 };
1292 if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)
1293 return feature_names[DCCPF_RESERVED];
1294
1295 if (feat == DCCPF_SEND_LEV_RATE)
1296 return "Send Loss Event Rate";
1297 if (feat >= DCCPF_MIN_CCID_SPECIFIC)
1298 return "CCID-specific";
1299
1300 return feature_names[feat];
1301}
1302#endif /* CONFIG_IP_DCCP_DEBUG */