diff options
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r-- | net/dccp/feat.c | 153 |
1 files changed, 107 insertions, 46 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 4c95cbdb0e01..3abacad0b224 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c | |||
@@ -204,6 +204,100 @@ static int dccp_feat_default_value(u8 feat_num) | |||
204 | return idx < 0 ? : dccp_feat_table[idx].default_value; | 204 | return idx < 0 ? : dccp_feat_table[idx].default_value; |
205 | } | 205 | } |
206 | 206 | ||
207 | /* | ||
208 | * Debugging and verbose-printing section | ||
209 | */ | ||
210 | static const char *dccp_feat_fname(const u8 feat) | ||
211 | { | ||
212 | static const char *feature_names[] = { | ||
213 | [DCCPF_RESERVED] = "Reserved", | ||
214 | [DCCPF_CCID] = "CCID", | ||
215 | [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", | ||
216 | [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", | ||
217 | [DCCPF_ECN_INCAPABLE] = "ECN Incapable", | ||
218 | [DCCPF_ACK_RATIO] = "Ack Ratio", | ||
219 | [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", | ||
220 | [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", | ||
221 | [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", | ||
222 | [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", | ||
223 | }; | ||
224 | if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) | ||
225 | return feature_names[DCCPF_RESERVED]; | ||
226 | |||
227 | if (feat == DCCPF_SEND_LEV_RATE) | ||
228 | return "Send Loss Event Rate"; | ||
229 | if (feat >= DCCPF_MIN_CCID_SPECIFIC) | ||
230 | return "CCID-specific"; | ||
231 | |||
232 | return feature_names[feat]; | ||
233 | } | ||
234 | |||
235 | static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING", | ||
236 | "UNSTABLE", "STABLE" }; | ||
237 | |||
238 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
239 | static const char *dccp_feat_oname(const u8 opt) | ||
240 | { | ||
241 | switch (opt) { | ||
242 | case DCCPO_CHANGE_L: return "Change_L"; | ||
243 | case DCCPO_CONFIRM_L: return "Confirm_L"; | ||
244 | case DCCPO_CHANGE_R: return "Change_R"; | ||
245 | case DCCPO_CONFIRM_R: return "Confirm_R"; | ||
246 | } | ||
247 | return NULL; | ||
248 | } | ||
249 | |||
250 | static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val) | ||
251 | { | ||
252 | u8 i, type = dccp_feat_type(feat_num); | ||
253 | |||
254 | if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL)) | ||
255 | dccp_pr_debug_cat("(NULL)"); | ||
256 | else if (type == FEAT_SP) | ||
257 | for (i = 0; i < val->sp.len; i++) | ||
258 | dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]); | ||
259 | else if (type == FEAT_NN) | ||
260 | dccp_pr_debug_cat("%llu", (unsigned long long)val->nn); | ||
261 | else | ||
262 | dccp_pr_debug_cat("unknown type %u", type); | ||
263 | } | ||
264 | |||
265 | static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len) | ||
266 | { | ||
267 | u8 type = dccp_feat_type(feat_num); | ||
268 | dccp_feat_val fval = { .sp.vec = list, .sp.len = len }; | ||
269 | |||
270 | if (type == FEAT_NN) | ||
271 | fval.nn = dccp_decode_value_var(list, len); | ||
272 | dccp_feat_printval(feat_num, &fval); | ||
273 | } | ||
274 | |||
275 | static void dccp_feat_print_entry(struct dccp_feat_entry const *entry) | ||
276 | { | ||
277 | dccp_debug(" * %s %s = ", entry->is_local ? "local" : "remote", | ||
278 | dccp_feat_fname(entry->feat_num)); | ||
279 | dccp_feat_printval(entry->feat_num, &entry->val); | ||
280 | dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state], | ||
281 | entry->needs_confirm ? "(Confirm pending)" : ""); | ||
282 | } | ||
283 | |||
284 | #define dccp_feat_print_opt(opt, feat, val, len, mandatory) do { \ | ||
285 | dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\ | ||
286 | dccp_feat_printvals(feat, val, len); \ | ||
287 | dccp_pr_debug_cat(") %s\n", mandatory ? "!" : ""); } while (0) | ||
288 | |||
289 | #define dccp_feat_print_fnlist(fn_list) { \ | ||
290 | const struct dccp_feat_entry *___entry; \ | ||
291 | \ | ||
292 | dccp_pr_debug("List Dump:\n"); \ | ||
293 | list_for_each_entry(___entry, fn_list, node) \ | ||
294 | dccp_feat_print_entry(___entry); \ | ||
295 | } | ||
296 | #else /* ! CONFIG_IP_DCCP_DEBUG */ | ||
297 | #define dccp_feat_print_opt(opt, feat, val, len, mandatory) | ||
298 | #define dccp_feat_print_fnlist(fn_list) | ||
299 | #endif | ||
300 | |||
207 | static int __dccp_feat_activate(struct sock *sk, const int idx, | 301 | static int __dccp_feat_activate(struct sock *sk, const int idx, |
208 | const bool is_local, dccp_feat_val const *fval) | 302 | const bool is_local, dccp_feat_val const *fval) |
209 | { | 303 | { |
@@ -236,6 +330,10 @@ static int __dccp_feat_activate(struct sock *sk, const int idx, | |||
236 | /* Location is RX if this is a local-RX or remote-TX feature */ | 330 | /* Location is RX if this is a local-RX or remote-TX feature */ |
237 | rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); | 331 | rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX)); |
238 | 332 | ||
333 | dccp_debug(" -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX", | ||
334 | dccp_feat_fname(dccp_feat_table[idx].feat_num), | ||
335 | fval ? "" : "default ", (unsigned long long)val); | ||
336 | |||
239 | return dccp_feat_table[idx].activation_hdlr(sk, val, rx); | 337 | return dccp_feat_table[idx].activation_hdlr(sk, val, rx); |
240 | } | 338 | } |
241 | 339 | ||
@@ -539,6 +637,7 @@ int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq, | |||
539 | return -1; | 637 | return -1; |
540 | } | 638 | } |
541 | } | 639 | } |
640 | dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0); | ||
542 | 641 | ||
543 | if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) | 642 | if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt)) |
544 | return -1; | 643 | return -1; |
@@ -792,6 +891,7 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp) | |||
792 | while (i--) | 891 | while (i--) |
793 | if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) | 892 | if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i)) |
794 | return -1; | 893 | return -1; |
894 | dccp_feat_print_fnlist(fn); | ||
795 | return 0; | 895 | return 0; |
796 | } | 896 | } |
797 | 897 | ||
@@ -910,6 +1010,8 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt, | |||
910 | if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ | 1010 | if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */ |
911 | goto unknown_feature_or_value; | 1011 | goto unknown_feature_or_value; |
912 | 1012 | ||
1013 | dccp_feat_print_opt(opt, feat, val, len, is_mandatory); | ||
1014 | |||
913 | /* | 1015 | /* |
914 | * Negotiation of NN features: Change R is invalid, so there is no | 1016 | * Negotiation of NN features: Change R is invalid, so there is no |
915 | * simultaneous negotiation; hence we do not look up in the list. | 1017 | * simultaneous negotiation; hence we do not look up in the list. |
@@ -1015,6 +1117,8 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt, | |||
1015 | const bool local = (opt == DCCPO_CONFIRM_R); | 1117 | const bool local = (opt == DCCPO_CONFIRM_R); |
1016 | struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); | 1118 | struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local); |
1017 | 1119 | ||
1120 | dccp_feat_print_opt(opt, feat, val, len, is_mandatory); | ||
1121 | |||
1018 | if (entry == NULL) { /* nothing queued: ignore or handle error */ | 1122 | if (entry == NULL) { /* nothing queued: ignore or handle error */ |
1019 | if (is_mandatory && type == FEAT_UNKNOWN) | 1123 | if (is_mandatory && type == FEAT_UNKNOWN) |
1020 | return DCCP_RESET_CODE_MANDATORY_ERROR; | 1124 | 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,47 +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 | ||
1265 | const 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 | |||
1278 | EXPORT_SYMBOL_GPL(dccp_feat_typename); | ||
1279 | |||
1280 | const char *dccp_feat_name(const u8 feat) | ||
1281 | { | ||
1282 | static const char *feature_names[] = { | ||
1283 | [DCCPF_RESERVED] = "Reserved", | ||
1284 | [DCCPF_CCID] = "CCID", | ||
1285 | [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos", | ||
1286 | [DCCPF_SEQUENCE_WINDOW] = "Sequence Window", | ||
1287 | [DCCPF_ECN_INCAPABLE] = "ECN Incapable", | ||
1288 | [DCCPF_ACK_RATIO] = "Ack Ratio", | ||
1289 | [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector", | ||
1290 | [DCCPF_SEND_NDP_COUNT] = "Send NDP Count", | ||
1291 | [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage", | ||
1292 | [DCCPF_DATA_CHECKSUM] = "Send Data Checksum", | ||
1293 | }; | ||
1294 | if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC) | ||
1295 | return feature_names[DCCPF_RESERVED]; | ||
1296 | |||
1297 | if (feat == DCCPF_SEND_LEV_RATE) | ||
1298 | return "Send Loss Event Rate"; | ||
1299 | if (feat >= DCCPF_MIN_CCID_SPECIFIC) | ||
1300 | return "CCID-specific"; | ||
1301 | |||
1302 | return feature_names[feat]; | ||
1303 | } | ||
1304 | |||
1305 | EXPORT_SYMBOL_GPL(dccp_feat_name); | ||
1306 | #endif /* CONFIG_IP_DCCP_DEBUG */ | ||