Currently, if a controller having a non zero id registers to get a OFPR_INVALID_TTL async message, it will not receive it. This is because compose_dec_ttl() only sent the invalid ttl packets to the default controller id. NXAST_DEC_TTL_CNT_IDS is a new action that accepts a list of controller ids, each separated by `:', to which the OFPR_INVALID_TTL packets must be sent. The earlier requirement of the controller having to explicitly register to receive these asynchronous messages is retained. The syntax of this action is: dec_ttl_cnt_ids=id1:id2 where id1, id2 are valid controller ids.
Signed-off-by: Mehak Mahajan <mmaha...@nicira.com> --- include/openflow/nicira-ext.h | 23 ++++++++++ lib/ofp-actions.c | 90 +++++++++++++++++++++++++++++++++++++++++ lib/ofp-actions.h | 69 ++++++++++++++++++------------- lib/ofp-parse.c | 28 +++++++++++++ lib/ofp-util.def | 39 +++++++++--------- ofproto/ofproto-dpif.c | 21 ++++++++- utilities/ovs-ofctl.8.in | 13 ++++-- 7 files changed, 229 insertions(+), 54 deletions(-) diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index 4fc2049..c209ba1 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -292,6 +292,7 @@ enum nx_action_subtype { NXAST_LEARN, /* struct nx_action_learn */ NXAST_EXIT, /* struct nx_action_header */ NXAST_DEC_TTL, /* struct nx_action_header */ + NXAST_DEC_TTL_CNT_IDS, /* struct nx_action_controller_ids */ NXAST_FIN_TIMEOUT, /* struct nx_action_fin_timeout */ NXAST_CONTROLLER, /* struct nx_action_controller */ }; @@ -1060,6 +1061,28 @@ enum nx_bd_algorithm { * Uses the 'fields' and 'basis' parameters. */ NX_BD_ALG_HRW /* Highest Random Weight. */ }; + + + /* Action structure for NXAST_DEC_TTL_CNT_IDS. + * + * The NXAST_DEC_TTL_CNT_IDS is used to send the packet to one or more + * controllers that have registered to receive the packet. + */ +struct nx_action_controller_ids { + ovs_be16 type; /* OFPAT_VENDOR. */ + ovs_be16 len; /* Length including slaves. */ + ovs_be32 vendor; /* NX_VENDOR_ID. */ + ovs_be16 subtype; /* NXAST_DEC_TTL_CNT_IDS. */ + + ovs_be16 n_controllers; /* Number of controllers. */ + uint8_t zeros[4]; /* Must be zero. */ + /* Followed by 1 or more controller ids. + * + * uint16_t *controller_ids; + */ +}; +OFP_ASSERT(sizeof(struct nx_action_controller_ids) == 16); + /* Action structure for NXAST_OUTPUT_REG. * diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 0874cc4..516d9ee 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -149,6 +149,44 @@ note_from_openflow(const struct nx_action_note *nan, struct ofpbuf *out) } static enum ofperr +dec_ttl_cnt_ids_from_openflow(const struct nx_action_controller_ids *nac_ids, + struct ofpbuf *out) +{ + struct ofpact_controller_ids *ids; + size_t ids_size; + enum ofperr error = 0; + int i; + + ids = ofpact_put_DEC_TTL_CNT_IDS(out); + ids->n_controllers = ntohs(nac_ids->n_controllers); + ids_size = ntohl(nac_ids->len) - sizeof *nac_ids; + + if (!is_all_zeros(nac_ids->zeros, sizeof nac_ids->zeros)) { + VLOG_WARN_RL(&rl, "reserved field is nonzero"); + error = OFPERR_OFPBAC_BAD_ARGUMENT; + VLOG_ERR("Came in here.\n"); + } + + if (ids_size < ids->n_controllers * sizeof(ovs_be16)) { + VLOG_WARN_RL(&rl, "Nicira action dec_ttl_cnt_ids only has %zu bytes " + "allocated for controller ids. %zu bytes are required for " + "%"PRIu16" controllers.", ids_size, + ids->n_controllers * sizeof(ovs_be16), ids->n_controllers); + error = OFPERR_OFPBAC_BAD_LEN; + } + + for (i = 0; i < ids->n_controllers; i++) { + uint16_t id = ntohs(((ovs_be16 *)(nac_ids + 1))[i]); + ofpbuf_put(out, &id, sizeof id); + } + + ids = out->l2; + ofpact_update_len(out, &ids->ofpact); + + return error; +} + +static enum ofperr decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code) { const struct nx_action_header *nah = (const struct nx_action_header *) a; @@ -313,6 +351,11 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code, ofpact_put_DEC_TTL(out); break; + case OFPUTIL_NXAST_DEC_TTL_CNT_IDS: + error = dec_ttl_cnt_ids_from_openflow( + (const struct nx_action_controller_ids *) a, out); + break; + case OFPUTIL_NXAST_FIN_TIMEOUT: fin_timeout_from_openflow( (const struct nx_action_fin_timeout *) a, out); @@ -951,6 +994,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports) return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow); case OFPACT_DEC_TTL: + case OFPACT_DEC_TTL_CNT_IDS: case OFPACT_SET_TUNNEL: case OFPACT_SET_QUEUE: case OFPACT_POP_QUEUE: @@ -1074,6 +1118,25 @@ ofpact_controller_to_nxast(const struct ofpact_controller *oc, } static void +ofpact_dec_ttl_cnt_ids_to_nxast(const struct ofpact_controller_ids *oc_ids, + struct ofpbuf *out) +{ + struct nx_action_controller_ids *nac_ids; + int ids_len = ROUND_UP(oc_ids->n_controllers, OFP_ACTION_ALIGN); + ovs_be16 *ids; + size_t i; + + nac_ids = ofputil_put_NXAST_DEC_TTL_CNT_IDS(out); + nac_ids->len = htons(ntohs(nac_ids->len) + ids_len); + nac_ids->n_controllers = htons(oc_ids->n_controllers); + + ids = ofpbuf_put_zeros(out, ids_len); + for (i = 0; i < oc_ids->n_controllers; i++) { + ids[i] = htons(oc_ids->controller_ids[i]); + } +} + +static void ofpact_fin_timeout_to_nxast(const struct ofpact_fin_timeout *fin_timeout, struct ofpbuf *out) { @@ -1110,6 +1173,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out) ofputil_put_NXAST_DEC_TTL(out); break; + case OFPACT_DEC_TTL_CNT_IDS: + ofpact_dec_ttl_cnt_ids_to_nxast(ofpact_get_DEC_TTL_CNT_IDS(a), out); + break; + case OFPACT_SET_TUNNEL: ofpact_set_tunnel_to_nxast(ofpact_get_SET_TUNNEL(a), out); break; @@ -1258,6 +1325,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out) case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: case OFPACT_DEC_TTL: + case OFPACT_DEC_TTL_CNT_IDS: case OFPACT_SET_TUNNEL: case OFPACT_SET_QUEUE: case OFPACT_POP_QUEUE: @@ -1366,6 +1434,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out) case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: case OFPACT_DEC_TTL: + case OFPACT_DEC_TTL_CNT_IDS: case OFPACT_SET_TUNNEL: case OFPACT_SET_QUEUE: case OFPACT_POP_QUEUE: @@ -1444,6 +1513,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port) case OFPACT_REG_MOVE: case OFPACT_REG_LOAD: case OFPACT_DEC_TTL: + case OFPACT_DEC_TTL_CNT_IDS: case OFPACT_SET_TUNNEL: case OFPACT_SET_QUEUE: case OFPACT_POP_QUEUE: @@ -1500,6 +1570,22 @@ print_note(const struct ofpact_note *note, struct ds *string) } static void +print_dec_ttl_cnt_ids(const struct ofpact_controller_ids *ids, + struct ds *s) +{ + size_t i; + + ds_put_cstr(s, "dec_ttl_cnt_ids (controller_ids:"); + for (i = 0; i < ids->n_controllers; i++) { + if (i) { + ds_put_cstr(s, ","); + } + ds_put_format(s, "%"PRIu16, ids->controller_ids[i]); + } + ds_put_cstr(s,")"); +} + +static void print_fin_timeout(const struct ofpact_fin_timeout *fin_timeout, struct ds *s) { @@ -1638,6 +1724,10 @@ ofpact_format(const struct ofpact *a, struct ds *s) ds_put_cstr(s, "dec_ttl"); break; + case OFPACT_DEC_TTL_CNT_IDS: + print_dec_ttl_cnt_ids(ofpact_get_DEC_TTL_CNT_IDS(a), s); + break; + case OFPACT_SET_TUNNEL: tunnel = ofpact_get_SET_TUNNEL(a); ds_put_format(s, "set_tunnel%s:%#"PRIx64, diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index 7c9cb05..0651971 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -50,44 +50,45 @@ */ #define OFPACTS \ /* Output. */ \ - DEFINE_OFPACT(OUTPUT, ofpact_output, ofpact) \ - DEFINE_OFPACT(CONTROLLER, ofpact_controller, ofpact) \ - DEFINE_OFPACT(ENQUEUE, ofpact_enqueue, ofpact) \ - DEFINE_OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact) \ - DEFINE_OFPACT(BUNDLE, ofpact_bundle, slaves) \ + DEFINE_OFPACT(OUTPUT, ofpact_output, ofpact) \ + DEFINE_OFPACT(CONTROLLER, ofpact_controller, ofpact) \ + DEFINE_OFPACT(ENQUEUE, ofpact_enqueue, ofpact) \ + DEFINE_OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact) \ + DEFINE_OFPACT(BUNDLE, ofpact_bundle, slaves) \ \ /* Header changes. */ \ - DEFINE_OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact) \ - DEFINE_OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact) \ - DEFINE_OFPACT(STRIP_VLAN, ofpact_null, ofpact) \ - DEFINE_OFPACT(SET_ETH_SRC, ofpact_mac, ofpact) \ - DEFINE_OFPACT(SET_ETH_DST, ofpact_mac, ofpact) \ - DEFINE_OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact) \ - DEFINE_OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact) \ - DEFINE_OFPACT(SET_IPV4_DSCP, ofpact_dscp, ofpact) \ - DEFINE_OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact) \ - DEFINE_OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact) \ - DEFINE_OFPACT(REG_MOVE, ofpact_reg_move, ofpact) \ - DEFINE_OFPACT(REG_LOAD, ofpact_reg_load, ofpact) \ - DEFINE_OFPACT(DEC_TTL, ofpact_null, ofpact) \ + DEFINE_OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact) \ + DEFINE_OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact) \ + DEFINE_OFPACT(STRIP_VLAN, ofpact_null, ofpact) \ + DEFINE_OFPACT(SET_ETH_SRC, ofpact_mac, ofpact) \ + DEFINE_OFPACT(SET_ETH_DST, ofpact_mac, ofpact) \ + DEFINE_OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact) \ + DEFINE_OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact) \ + DEFINE_OFPACT(SET_IPV4_DSCP, ofpact_dscp, ofpact) \ + DEFINE_OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact) \ + DEFINE_OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact) \ + DEFINE_OFPACT(REG_MOVE, ofpact_reg_move, ofpact) \ + DEFINE_OFPACT(REG_LOAD, ofpact_reg_load, ofpact) \ + DEFINE_OFPACT(DEC_TTL, ofpact_null, ofpact) \ \ /* Metadata. */ \ - DEFINE_OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact) \ - DEFINE_OFPACT(SET_QUEUE, ofpact_queue, ofpact) \ - DEFINE_OFPACT(POP_QUEUE, ofpact_null, ofpact) \ - DEFINE_OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact) \ + DEFINE_OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact) \ + DEFINE_OFPACT(SET_QUEUE, ofpact_queue, ofpact) \ + DEFINE_OFPACT(POP_QUEUE, ofpact_null, ofpact) \ + DEFINE_OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact) \ \ /* Flow table interaction. */ \ - DEFINE_OFPACT(RESUBMIT, ofpact_resubmit, ofpact) \ - DEFINE_OFPACT(LEARN, ofpact_learn, specs) \ + DEFINE_OFPACT(RESUBMIT, ofpact_resubmit, ofpact) \ + DEFINE_OFPACT(LEARN, ofpact_learn, specs) \ \ /* Arithmetic. */ \ - DEFINE_OFPACT(MULTIPATH, ofpact_multipath, ofpact) \ - DEFINE_OFPACT(AUTOPATH, ofpact_autopath, ofpact) \ + DEFINE_OFPACT(MULTIPATH, ofpact_multipath, ofpact) \ + DEFINE_OFPACT(AUTOPATH, ofpact_autopath, ofpact) \ \ /* Other. */ \ - DEFINE_OFPACT(NOTE, ofpact_note, data) \ - DEFINE_OFPACT(EXIT, ofpact_null, ofpact) + DEFINE_OFPACT(DEC_TTL_CNT_IDS, ofpact_controller_ids, controller_ids) \ + DEFINE_OFPACT(NOTE, ofpact_note, data) \ + DEFINE_OFPACT(EXIT, ofpact_null, ofpact) /* enum ofpact_type, with a member OFPACT_<ENUM> for each action. */ enum OVS_PACKED_ENUM ofpact_type { @@ -380,6 +381,18 @@ struct ofpact_note { uint8_t data[]; }; +/* OFPACT_DEC_TTL_CNT_IDS + * + * Used for NXAST_DEC_TTL_CNT_IDS. */ +struct ofpact_controller_ids { + struct ofpact ofpact; + + /* Controller ids. */ + unsigned int n_controllers; + uint16_t controller_ids[]; + +}; + /* Converting OpenFlow to ofpacts. */ enum ofperr ofpacts_pull_openflow10(struct ofpbuf *openflow, unsigned int actions_len, diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 32d3836..9415fa6 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -279,6 +279,30 @@ parse_controller(struct ofpbuf *b, char *arg) } static void +parse_dec_ttl_cnt_ids(struct ofpbuf *b, char *arg) +{ + struct ofpact_controller_ids *ids; + + if (*arg == '\0') { + ovs_fatal(0, "dec_ttl_cnt_ids: expected atleast one controler id."); + } + + ids = ofpact_put_DEC_TTL_CNT_IDS(b); + while(*arg != '\0') { + char *cntr; + uint16_t id; + + cntr = strtok_r(NULL, ": ", &arg); + id = atoi(cntr); + ofpbuf_put(b, &id, sizeof id); + + ids = b->l2; + ids->n_controllers++; + } + ofpact_update_len(b, &ids->ofpact); +} + +static void parse_named_action(enum ofputil_action_code code, const struct flow *flow, char *arg, struct ofpbuf *ofpacts) { @@ -427,6 +451,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, ofpact_put_DEC_TTL(ofpacts); break; + case OFPUTIL_NXAST_DEC_TTL_CNT_IDS: + parse_dec_ttl_cnt_ids(ofpacts, arg); + break; + case OFPUTIL_NXAST_FIN_TIMEOUT: parse_fin_timeout(ofpacts, arg); break; diff --git a/lib/ofp-util.def b/lib/ofp-util.def index 974cd8f..6ae8a63 100644 --- a/lib/ofp-util.def +++ b/lib/ofp-util.def @@ -39,25 +39,26 @@ OFPAT11_ACTION(OFPAT11_SET_TP_DST, ofp_action_tp_port, "mod_tp_dst") #ifndef NXAST_ACTION #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) #endif -NXAST_ACTION(NXAST_RESUBMIT, nx_action_resubmit, 0, "resubmit") -NXAST_ACTION(NXAST_SET_TUNNEL, nx_action_set_tunnel, 0, "set_tunnel") -NXAST_ACTION(NXAST_SET_QUEUE, nx_action_set_queue, 0, "set_queue") -NXAST_ACTION(NXAST_POP_QUEUE, nx_action_pop_queue, 0, "pop_queue") -NXAST_ACTION(NXAST_REG_MOVE, nx_action_reg_move, 0, "move") -NXAST_ACTION(NXAST_REG_LOAD, nx_action_reg_load, 0, "load") -NXAST_ACTION(NXAST_NOTE, nx_action_note, 1, "note") -NXAST_ACTION(NXAST_SET_TUNNEL64, nx_action_set_tunnel64, 0, "set_tunnel64") -NXAST_ACTION(NXAST_MULTIPATH, nx_action_multipath, 0, "multipath") -NXAST_ACTION(NXAST_AUTOPATH, nx_action_autopath, 0, "autopath") -NXAST_ACTION(NXAST_BUNDLE, nx_action_bundle, 1, "bundle") -NXAST_ACTION(NXAST_BUNDLE_LOAD, nx_action_bundle, 1, "bundle_load") -NXAST_ACTION(NXAST_RESUBMIT_TABLE, nx_action_resubmit, 0, NULL) -NXAST_ACTION(NXAST_OUTPUT_REG, nx_action_output_reg, 0, NULL) -NXAST_ACTION(NXAST_LEARN, nx_action_learn, 1, "learn") -NXAST_ACTION(NXAST_EXIT, nx_action_header, 0, "exit") -NXAST_ACTION(NXAST_DEC_TTL, nx_action_header, 0, "dec_ttl") -NXAST_ACTION(NXAST_FIN_TIMEOUT, nx_action_fin_timeout, 0, "fin_timeout") -NXAST_ACTION(NXAST_CONTROLLER, nx_action_controller, 0, "controller") +NXAST_ACTION(NXAST_RESUBMIT, nx_action_resubmit, 0, "resubmit") +NXAST_ACTION(NXAST_SET_TUNNEL, nx_action_set_tunnel, 0, "set_tunnel") +NXAST_ACTION(NXAST_SET_QUEUE, nx_action_set_queue, 0, "set_queue") +NXAST_ACTION(NXAST_POP_QUEUE, nx_action_pop_queue, 0, "pop_queue") +NXAST_ACTION(NXAST_REG_MOVE, nx_action_reg_move, 0, "move") +NXAST_ACTION(NXAST_REG_LOAD, nx_action_reg_load, 0, "load") +NXAST_ACTION(NXAST_NOTE, nx_action_note, 1, "note") +NXAST_ACTION(NXAST_SET_TUNNEL64, nx_action_set_tunnel64, 0, "set_tunnel64") +NXAST_ACTION(NXAST_MULTIPATH, nx_action_multipath, 0, "multipath") +NXAST_ACTION(NXAST_AUTOPATH, nx_action_autopath, 0, "autopath") +NXAST_ACTION(NXAST_BUNDLE, nx_action_bundle, 1, "bundle") +NXAST_ACTION(NXAST_BUNDLE_LOAD, nx_action_bundle, 1, "bundle_load") +NXAST_ACTION(NXAST_RESUBMIT_TABLE, nx_action_resubmit, 0, NULL) +NXAST_ACTION(NXAST_OUTPUT_REG, nx_action_output_reg, 0, NULL) +NXAST_ACTION(NXAST_LEARN, nx_action_learn, 1, "learn") +NXAST_ACTION(NXAST_EXIT, nx_action_header, 0, "exit") +NXAST_ACTION(NXAST_DEC_TTL, nx_action_header, 0, "dec_ttl") +NXAST_ACTION(NXAST_DEC_TTL_CNT_IDS, nx_action_controller_ids, 1, "dec_ttl_cnt_ids") +NXAST_ACTION(NXAST_FIN_TIMEOUT, nx_action_fin_timeout, 0, "fin_timeout") +NXAST_ACTION(NXAST_CONTROLLER, nx_action_controller, 0, "controller") #undef OFPAT10_ACTION #undef OFPAT11_ACTION diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 95195a3..309cb27 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5134,7 +5134,7 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len, } static bool -compose_dec_ttl(struct action_xlate_ctx *ctx) +compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_controller_ids *ids) { if (ctx->flow.dl_type != htons(ETH_TYPE_IP) && ctx->flow.dl_type != htons(ETH_TYPE_IPV6)) { @@ -5145,7 +5145,16 @@ compose_dec_ttl(struct action_xlate_ctx *ctx) ctx->flow.nw_ttl--; return false; } else { - execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0); + if (!ids) { + execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0); + } else { + size_t i; + + for (i = 0; i < ids->n_controllers; i++) { + execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, + ids->controller_ids[i]); + } + } /* Stop processing for current table. */ return true; @@ -5505,7 +5514,13 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_DEC_TTL: - if (compose_dec_ttl(ctx)) { + if (compose_dec_ttl(ctx, NULL)) { + goto out; + } + break; + + case OFPACT_DEC_TTL_CNT_IDS: + if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL_CNT_IDS(a))) { goto out; } break; diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 65fc6e8..76f2f74 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -945,12 +945,17 @@ actions were applied. Decrement TTL of IPv4 packet or hop limit of IPv6 packet. If the TTL or hop limit is initially zero, no decrement occurs. Instead, a ``packet-in'' message with reason code \fBOFPR_INVALID_TTL\fR is -sent to each connected controller that has enabled receiving them, -if any. Processing the current set of actions then stops. -However, if the current set of actions was reached through -``resubmit'' then remaining actions in outer levels resume +sent to each connected controller whose controller id is 0 and that +has enabled receiving them, if any. Processing the current set of +actions then stops. However, if the current set of actions was reached +through ``resubmit'' then remaining actions in outer levels resume processing. . +.IP \fBdec_ttl_cnt_ids\fB=\fIid1\fB:\fIid2\fR +Same as dec_ttl, except it accepts a list of controller ids to whom +the ``packet-in'' message with reason code \fBOFPR_INVALID_TTL\fR +must be sent. +. .IP \fBnote:\fR[\fIhh\fR]... Does nothing at all. Any number of bytes represented as hex digits \fIhh\fR may be included. Pairs of hex digits may be separated by -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev