diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2009-01-16 18:36:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-21 17:34:05 -0500 |
commit | f3f3abb62ccb1a1c77bcce855c04e12356e6ac95 (patch) | |
tree | 6b3e73207a047e600ab44bfe126132c538f4d772 /net/dccp/feat.c | |
parent | 883ca833e5fb814fb03426c9d35e5489ce43e8da (diff) |
dccp: Debugging functions for feature negotiation
Since all feature-negotiation processing now takes place in feat.c,
functions for producing verbose debugging output are concentrated
there.
New functions to print out values, entry records, and options are
provided, and also a macro is defined to not always have the function
name in the output line.
Thanks a lot to Wei Yongjun and Giuseppe Galeota for help and
discussion with an earlier revision of this patch.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r-- | net/dccp/feat.c | 149 |
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 | */ | ||
214 | static 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 | |||
239 | static const char *dccp_feat_sname[] = { "DEFAULT", "INITIALISING", "CHANGING", | ||
240 | "UNSTABLE", "STABLE" }; | ||
241 | |||
242 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
243 | static 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 | |||
254 | static 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 | |||
269 | static 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 | |||
279 | static 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 | |||
211 | static int __dccp_feat_activate(struct sock *sk, const int idx, | 305 | static 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 | ||
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 | const 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 */ | ||