In the new documentation, invalid_ttl should be bold instead of italic, because it is a literal string. If you fix that, then this looks good. Thank you!
On Fri, Jan 13, 2012 at 05:13:48PM -0800, Pravin B Shelar wrote: > Fixed according to comments from Ben. > > v2-v3: > - Updated ovs-ofctl monitor documentation. > v1-v2: > - Fixed man page > - Added invalid-ttl arg for ofctl-monitor. > - Added invalid-ttl packet-in test case. > > --8<--------------------------cut here-------------------------->8- > Following patch implements dec_ttl as vendor action with similar > semantics as OpenFlow 1.2. If TTL reaches zero while procession > actions in current table, the remaining actions in previous tables > are processed. An configuration parameter is added to make TTL > decrement to zero generate packet in. > > Feature #8758 > --- > NEWS | 1 + > include/openflow/nicira-ext.h | 3 +- > include/openflow/openflow.h | 9 ++++++- > lib/ofp-parse.c | 4 +++ > lib/ofp-print.c | 24 ++++++++++++++++++-- > lib/ofp-util.c | 1 + > lib/ofp-util.def | 1 + > lib/ofp-util.h | 2 +- > ofproto/connmgr.c | 46 ++++++++++++++++++++++++++++++++++++---- > ofproto/connmgr.h | 3 ++ > ofproto/ofproto-dpif.c | 36 +++++++++++++++++++++++++++++-- > ofproto/ofproto.c | 9 +++++++- > tests/ofp-print.at | 2 +- > tests/ofproto-dpif.at | 38 +++++++++++++++++++++++++++++++-- > utilities/ovs-ofctl.8.in | 19 ++++++++++++++++- > utilities/ovs-ofctl.c | 36 +++++++++++++++++++++++++++++++- > 16 files changed, 212 insertions(+), 22 deletions(-) > > diff --git a/NEWS b/NEWS > index b628e29..4f29e19 100644 > --- a/NEWS > +++ b/NEWS > @@ -8,6 +8,7 @@ v1.5.0 - xx xxx xxxx > - Added support for querying, modifying, and deleting flows > based on flow cookie when using NXM. > - Added new NXM_PACKET_IN format. > + - Added new NXAST_DEC_TTL action. > - ovs-ofctl: > - Added daemonization support to the monitor and snoop commands. > - ovs-vsctl: > diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h > index f00f994..e17b313 100644 > --- a/include/openflow/nicira-ext.h > +++ b/include/openflow/nicira-ext.h > @@ -361,7 +361,8 @@ enum nx_action_subtype { > NXAST_RESUBMIT_TABLE, /* struct nx_action_resubmit */ > NXAST_OUTPUT_REG, /* struct nx_action_output_reg */ > NXAST_LEARN, /* struct nx_action_learn */ > - NXAST_EXIT /* struct nx_action_header */ > + NXAST_EXIT, /* struct nx_action_header */ > + NXAST_DEC_TTL, /* struct nx_action_header */ > }; > > /* Header for Nicira-defined actions. */ > diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h > index f68a140..cd30d32 100644 > --- a/include/openflow/openflow.h > +++ b/include/openflow/openflow.h > @@ -136,7 +136,11 @@ enum ofp_config_flags { > OFPC_FRAG_DROP = 1, /* Drop fragments. */ > OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */ > OFPC_FRAG_NX_MATCH = 3, /* Make first fragments available for matching. > */ > - OFPC_FRAG_MASK = 3 > + OFPC_FRAG_MASK = 3, > + > + /* TTL processing - applicable for IP and MPLS packets. */ > + OFPC_INVALID_TTL_TO_CONTROLLER = 1 << 2, /* Send packets with invalid TTL > + to the controller. */ > }; > > /* Switch configuration. */ > @@ -289,7 +293,8 @@ OFP_ASSERT(sizeof(struct ofp_port_mod) == 32); > /* Why is this packet being sent to the controller? */ > enum ofp_packet_in_reason { > OFPR_NO_MATCH, /* No matching flow. */ > - OFPR_ACTION /* Action explicitly output to controller. */ > + OFPR_ACTION, /* Action explicitly output to controller. */ > + OFPR_INVALID_TTL /* Packet has invalid TTL. */ > }; > > /* Packet received on port (datapath -> controller). */ > diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c > index 38c3dab..5321364 100644 > --- a/lib/ofp-parse.c > +++ b/lib/ofp-parse.c > @@ -364,6 +364,10 @@ parse_named_action(enum ofputil_action_code code, const > struct flow *flow, > case OFPUTIL_NXAST_EXIT: > ofputil_put_NXAST_EXIT(b); > break; > + > + case OFPUTIL_NXAST_DEC_TTL: > + ofputil_put_NXAST_DEC_TTL(b); > + break; > } > } > > diff --git a/lib/ofp-print.c b/lib/ofp-print.c > index aff12b6..0775ea6 100644 > --- a/lib/ofp-print.c > +++ b/lib/ofp-print.c > @@ -120,10 +120,19 @@ ofp_print_packet_in(struct ds *string, const struct > ofp_header *oh, > } > } > > - if (pin.reason == OFPR_ACTION) { > + switch (pin.reason) { > + case OFPR_NO_MATCH: > + ds_put_cstr(string, " (via no_match)"); > + break; > + case OFPR_ACTION: > ds_put_cstr(string, " (via action)"); > - } else if (pin.reason != OFPR_NO_MATCH) { > + break; > + case OFPR_INVALID_TTL: > + ds_put_cstr(string, " (via invalid_ttl)"); > + break; > + default: > ds_put_format(string, " (***reason %"PRIu8"***)", pin.reason); > + break; > } > > ds_put_format(string, " data_len=%zu", pin.packet_len); > @@ -333,6 +342,10 @@ ofp_print_action(struct ds *s, const union ofp_action *a, > learn_format((const struct nx_action_learn *) a, s); > break; > > + case OFPUTIL_NXAST_DEC_TTL: > + ds_put_cstr(s, "dec_ttl"); > + break; > + > case OFPUTIL_NXAST_EXIT: > ds_put_cstr(s, "exit"); > break; > @@ -599,13 +612,18 @@ ofp_print_switch_features(struct ds *string, > static void > ofp_print_switch_config(struct ds *string, const struct ofp_switch_config > *osc) > { > - uint16_t flags; > + enum ofp_config_flags flags; > > flags = ntohs(osc->flags); > > ds_put_format(string, " frags=%s", > ofputil_frag_handling_to_string(flags)); > flags &= ~OFPC_FRAG_MASK; > > + if (flags & OFPC_INVALID_TTL_TO_CONTROLLER) { > + ds_put_format(string, " invalid_ttl_to_controller"); > + flags &= ~OFPC_INVALID_TTL_TO_CONTROLLER; > + } > + > if (flags) { > ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags); > } > diff --git a/lib/ofp-util.c b/lib/ofp-util.c > index b20d3fb..6fe1611 100644 > --- a/lib/ofp-util.c > +++ b/lib/ofp-util.c > @@ -2436,6 +2436,7 @@ validate_actions(const union ofp_action *actions, > size_t n_actions, > case OFPUTIL_NXAST_NOTE: > case OFPUTIL_NXAST_SET_TUNNEL64: > case OFPUTIL_NXAST_EXIT: > + case OFPUTIL_NXAST_DEC_TTL: > break; > } > > diff --git a/lib/ofp-util.def b/lib/ofp-util.def > index 2958eb6..d05ec9d 100644 > --- a/lib/ofp-util.def > +++ b/lib/ofp-util.def > @@ -36,4 +36,5 @@ 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") > #undef NXAST_ACTION > diff --git a/lib/ofp-util.h b/lib/ofp-util.h > index d01e17a..422c14a 100644 > --- a/lib/ofp-util.h > +++ b/lib/ofp-util.h > @@ -227,7 +227,7 @@ struct ofputil_packet_in { > const void *packet; > size_t packet_len; > > - uint8_t reason; /* One of OFPR_*. */ > + enum ofp_packet_in_reason reason; /* One of OFPRR_*. */ > uint8_t table_id; > ovs_be64 cookie; > > diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c > index 28d9488..887080a 100644 > --- a/ofproto/connmgr.c > +++ b/ofproto/connmgr.c > @@ -71,6 +71,8 @@ struct ofconn { > > /* type == OFCONN_PRIMARY only. */ > enum nx_role role; /* Role. */ > + bool invalid_ttl_to_controller; /* Send packets with invalid TTL > + to the controller. */ > struct hmap_node hmap_node; /* In struct connmgr's "controllers" map. */ > enum ofproto_band band; /* In-band or out-of-band? */ > }; > @@ -754,6 +756,18 @@ ofconn_set_role(struct ofconn *ofconn, enum nx_role role) > ofconn->role = role; > } > > +void > +ofconn_set_invalid_ttl_to_controller(struct ofconn *ofconn, bool val) > +{ > + ofconn->invalid_ttl_to_controller = val; > +} > + > +bool > +ofconn_get_invalid_ttl_to_controller(struct ofconn *ofconn) > +{ > + return ofconn->invalid_ttl_to_controller; > +} > + > /* Returns the currently configured flow format for 'ofconn', one of NXFF_*. > * > * The default, if no other format has been set, is NXFF_OPENFLOW10. */ > @@ -931,6 +945,7 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, > enum ofconn_type type) > ofconn->pktbuf = NULL; > ofconn->miss_send_len = 0; > ofconn->reply_counter = rconn_packet_counter_create (); > + ofconn->invalid_ttl_to_controller = false; > return ofconn; > } > > @@ -1054,11 +1069,9 @@ ofconn_wait(struct ofconn *ofconn, bool > handling_openflow) > > /* Returns true if 'ofconn' should receive asynchronous messages. */ > static bool > -ofconn_receives_async_msgs(const struct ofconn *ofconn) > +ofconn_receives_async_msgs__(const struct ofconn *ofconn) > { > - if (!rconn_is_connected(ofconn->rconn)) { > - return false; > - } else if (ofconn->type == OFCONN_PRIMARY) { > + if (ofconn->type == OFCONN_PRIMARY) { > /* Primary controllers always get asynchronous messages unless they > * have configured themselves as "slaves". */ > return ofconn->role != NX_ROLE_SLAVE; > @@ -1069,6 +1082,29 @@ ofconn_receives_async_msgs(const struct ofconn *ofconn) > } > } > > +static bool > +ofconn_receives_async_msgs(const struct ofconn *ofconn) > +{ > + if (!rconn_is_connected(ofconn->rconn)) { > + return false; > + } else { > + return ofconn_receives_async_msgs__(ofconn); > + } > +} > + > +static bool > +ofconn_interested_in_packet(const struct ofconn *ofconn, > + const struct ofputil_packet_in *pin) > +{ > + if (!rconn_is_connected(ofconn->rconn)) { > + return false; > + } else if (pin->reason == OFPR_INVALID_TTL) { > + return ofconn->invalid_ttl_to_controller; > + } else { > + return ofconn_receives_async_msgs__(ofconn); > + } > +} > + > /* Returns a human-readable name for an OpenFlow connection between 'mgr' and > * 'target', suitable for use in log messages for identifying the connection. > * > @@ -1178,7 +1214,7 @@ connmgr_send_packet_in(struct connmgr *mgr, > struct ofconn *ofconn; > > LIST_FOR_EACH (ofconn, node, &mgr->all_conns) { > - if (ofconn_receives_async_msgs(ofconn)) { > + if (ofconn_interested_in_packet(ofconn, pin)) { > schedule_packet_in(ofconn, *pin, flow); > } > } > diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h > index bbee7f4..8ff89f3 100644 > --- a/ofproto/connmgr.h > +++ b/ofproto/connmgr.h > @@ -92,6 +92,9 @@ void ofconn_set_packet_in_format(struct ofconn *, enum > nx_packet_in_format); > bool ofconn_get_flow_mod_table_id(const struct ofconn *); > void ofconn_set_flow_mod_table_id(struct ofconn *, bool enable); > > +void ofconn_set_invalid_ttl_to_controller(struct ofconn *, bool); > +bool ofconn_get_invalid_ttl_to_controller(struct ofconn *); > + > int ofconn_get_miss_send_len(const struct ofconn *); > void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len); > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 6ecf71b..567240d 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -4291,7 +4291,8 @@ flood_packets(struct action_xlate_ctx *ctx, bool all) > } > > static void > -execute_controller_action(struct action_xlate_ctx *ctx, int len) > +execute_controller_action(struct action_xlate_ctx *ctx, int len, > + enum ofp_packet_in_reason reason) > { > struct ofputil_packet_in pin; > struct ofpbuf *packet; > @@ -4336,7 +4337,7 @@ execute_controller_action(struct action_xlate_ctx *ctx, > int len) > > pin.packet = packet->data; > pin.packet_len = packet->size; > - pin.reason = OFPR_ACTION; > + pin.reason = reason; > pin.table_id = ctx->table_id; > pin.cookie = ctx->cookie; > > @@ -4349,6 +4350,25 @@ execute_controller_action(struct action_xlate_ctx > *ctx, int len) > ofpbuf_delete(packet); > } > > +static bool > +compose_dec_ttl(struct action_xlate_ctx *ctx) > +{ > + if (ctx->flow.dl_type != htons(ETH_TYPE_IP) && > + ctx->flow.dl_type != htons(ETH_TYPE_IPV6)) { > + return false; > + } > + > + if (ctx->flow.nw_ttl > 1) { > + ctx->flow.nw_ttl--; > + return false; > + } else { > + execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL); > + > + /* Stop processing for current table. */ > + return true; > + } > +} > + > static void > xlate_output_action__(struct action_xlate_ctx *ctx, > uint16_t port, uint16_t max_len) > @@ -4374,7 +4394,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx, > flood_packets(ctx, true); > break; > case OFPP_CONTROLLER: > - execute_controller_action(ctx, max_len); > + execute_controller_action(ctx, max_len, OFPR_ACTION); > break; > case OFPP_LOCAL: > compose_output_action(ctx, OFPP_LOCAL); > @@ -4730,12 +4750,19 @@ do_xlate_actions(const union ofp_action *in, size_t > n_in, > } > break; > > + case OFPUTIL_NXAST_DEC_TTL: > + if (compose_dec_ttl(ctx)) { > + goto out; > + } > + break; > + > case OFPUTIL_NXAST_EXIT: > ctx->exit = true; > break; > } > } > > +out: > /* We've let OFPP_NORMAL and the learning action look at the packet, > * so drop it now if forwarding is disabled. */ > if (port && !stp_forward_in_state(port->stp_state)) { > @@ -4799,6 +4826,9 @@ xlate_actions(struct action_xlate_ctx *ctx, > case OFPC_FRAG_NX_MATCH: > /* Nothing to do. */ > break; > + > + case OFPC_INVALID_TTL_TO_CONTROLLER: > + NOT_REACHED(); > } > } > > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index 29259e4..0504026 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -1746,11 +1746,16 @@ handle_get_config_request(struct ofconn *ofconn, > const struct ofp_header *oh) > { > struct ofproto *ofproto = ofconn_get_ofproto(ofconn); > struct ofp_switch_config *osc; > + enum ofp_config_flags flags; > struct ofpbuf *buf; > > /* Send reply. */ > osc = make_openflow_xid(sizeof *osc, OFPT_GET_CONFIG_REPLY, oh->xid, > &buf); > - osc->flags = htons(ofproto->frag_handling); > + flags = ofproto->frag_handling; > + if (ofconn_get_invalid_ttl_to_controller(ofconn)) { > + flags |= OFPC_INVALID_TTL_TO_CONTROLLER; > + } > + osc->flags = htons(flags); > osc->miss_send_len = htons(ofconn_get_miss_send_len(ofconn)); > ofconn_send_reply(ofconn, buf); > > @@ -1779,6 +1784,8 @@ handle_set_config(struct ofconn *ofconn, const struct > ofp_switch_config *osc) > } > } > } > + ofconn_set_invalid_ttl_to_controller(ofconn, > + (flags & OFPC_INVALID_TTL_TO_CONTROLLER)); > > ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len)); > > diff --git a/tests/ofp-print.at b/tests/ofp-print.at > index 0619e98..85562b6 100644 > --- a/tests/ofp-print.at > +++ b/tests/ofp-print.at > @@ -269,7 +269,7 @@ AT_CHECK([ovs-ofctl ofp-print "\ > c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \ > 50 00 02 00 26 e8 00 00 00 00 00 00 00 00 \ > "], [0], [dnl > -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 data_len=60 > buffer=0x00000111 > +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 (via no_match) data_len=60 > buffer=0x00000111 > priority:0,tunnel:0,in_port:0000,tci(0) > mac(50:54:00:00:00:05->50:54:00:00:00:06) type:0800 proto:6 tos:0 ttl:64 > ip(192.168.0.1->192.168.0.2) port(10031->0) tcp_csum:26e8 > ]) > AT_CLEANUP > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index 2c4e7c4..bb00714 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -62,6 +62,38 @@ AT_CHECK([tail -1 stdout], [0], > OVS_VSWITCHD_STOP > AT_CLEANUP > > +AT_SETUP([ofproto-dpif - dec_ttl]) > +OVS_VSWITCHD_START > +AT_DATA([flows.txt], [dnl > +table=0 in_port=1 action=dec_ttl,output:2,resubmit(1,1),output:4 > +table=1 in_port=1 action=dec_ttl,output:3 > +]) > +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) > +AT_CHECK([ovs-appctl ofproto/trace br0 > 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' > -generate], [0], [stdout]) > +AT_CHECK([tail -2 stdout], [0], > + [Datapath actions: > set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),2,4 > +This flow is not cachable. > +]) > +AT_CHECK([ovs-appctl ofproto/trace br0 > 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=3,frag=no)'], > [0], [stdout]) > +AT_CHECK([tail -1 stdout], [0], > + [Datapath actions: > set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)),2,set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),3,4 > +]) > +AT_CHECK([ovs-appctl ofproto/trace br0 > 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], > [0], [stdout]) > +AT_CHECK([tail -1 stdout], [0], > + [Datapath actions: > set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=127,frag=no)),2,set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=126,frag=no)),3,4 > +]) > + > +AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl --detach --pidfile 2> > ofctl_monitor.log]) > +AT_CHECK([ovs-appctl ofproto/trace br0 > 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' > -generate], [0], [stdout]) > +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > +NXT_PACKET_IN (xid=0x0): table_id=1 total_len=42 in_port=1 tun_id=0x0 > reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 (via invalid_ttl) data_len=42 > (unbuffered) > +priority:0,tunnel:0,in_port:0000,tci(0) > mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:1 tos:0 ttl:1 > ip(192.168.0.1->192.168.0.2) > +]) > +OVS_VSWITCHD_STOP > +AT_CLEANUP > + > + > AT_SETUP([ofproto-dpif - output, OFPP_NONE ingress port]) > OVS_VSWITCHD_START( > [add-port br0 p1 -- set Interface p1 type=dummy --\ > @@ -209,13 +241,13 @@ done > > OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > AT_CHECK([cat ofctl_monitor.log], [0], [dnl > -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 data_len=60 (unbuffered) > +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(0) > mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 data_len=60 (unbuffered) > +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(0) > mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 data_len=60 (unbuffered) > +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(0) > mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0 > ]) > > diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in > index 4bfd543..53d8619 100644 > --- a/utilities/ovs-ofctl.8.in > +++ b/utilities/ovs-ofctl.8.in > @@ -243,7 +243,7 @@ If a switch has no controller configured, or if > the configured controller is disconnected, no traffic is sent, so > monitoring will not show any traffic. > . > -.IP "\fBmonitor \fIswitch\fR [\fImiss-len\fR]" > +.IP "\fBmonitor \fIswitch\fR [\fImiss-len\fR] [\fIinvalid_ttl\fR]" > Connects to \fIswitch\fR and prints to the console all OpenFlow > messages received. Usually, \fIswitch\fR should specify the name of a > bridge in the \fBovs\-vswitchd\fR database. > @@ -256,6 +256,13 @@ does not send these and other asynchronous messages to an > specified on this argument. (Thus, if \fImiss\-len\fR is not > specified, very little traffic will ordinarily be printed.) > .IP > +.IP > +If \fIinvalid_ttl\fR is passed, \fBovs\-ofctl\fR sends an OpenFlow ``set > +configuration'' message at connection setup time that requests > +\fIINVALID_TTL_TO_CONTROLLER\fR, so that \fBovs\-ofctl monitor\fR can > +receive ``packets-in'' messages when TTL reaches zero on \fBdec_ttl\fR > action. > +.IP > + > This command may be useful for debugging switch or controller > implementations. > . > @@ -778,6 +785,16 @@ OpenFlow implementations do not support queuing at all. > Restores the queue to the value it was before any \fBset_queue\fR > actions were applied. > . > +.IP \fBdec_ttl\fR > +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 > +processing. > +. > .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 > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > index 6219f94..8a8b8b2 100644 > --- a/utilities/ovs-ofctl.c > +++ b/utilities/ovs-ofctl.c > @@ -794,6 +794,35 @@ set_packet_in_format(struct vconn *vconn, > ofputil_packet_in_format_to_string(packet_in_format)); > } > > +static int > +monitor_set_invalid_ttl_to_controller(struct vconn *vconn) > +{ > + struct ofp_switch_config config; > + enum ofp_config_flags flags; > + > + fetch_switch_config(vconn, &config); > + flags = ntohs(config.flags); > + if (!(flags & OFPC_INVALID_TTL_TO_CONTROLLER)) { > + /* Set the invalid ttl config. */ > + flags |= OFPC_INVALID_TTL_TO_CONTROLLER; > + > + config.flags = htons(flags); > + set_switch_config(vconn, &config); > + > + /* Then retrieve the configuration to see if it really took. > OpenFlow > + * doesn't define error reporting for bad modes, so this is all we > can > + * do. */ > + fetch_switch_config(vconn, &config); > + flags = ntohs(config.flags); > + if (!(flags & OFPC_INVALID_TTL_TO_CONTROLLER)) { > + ovs_fatal(0, "setting invalid_ttl_to_controller failed (this " > + "switch probably doesn't support mode)"); > + return -EOPNOTSUPP; > + } > + } > + return 0; > +} > + > static void > monitor_vconn(struct vconn *vconn) > { > @@ -876,6 +905,11 @@ do_monitor(int argc, char *argv[]) > config.miss_send_len = htons(atoi(argv[2])); > set_switch_config(vconn, &config); > } > + if (argc > 3) { > + if (!strcmp(argv[3], "invalid_ttl")) { > + monitor_set_invalid_ttl_to_controller(vconn); > + } > + } > monitor_vconn(vconn); > } > > @@ -1634,7 +1668,7 @@ do_ofp_print(int argc, char *argv[]) > > static const struct command all_commands[] = { > { "show", 1, 1, do_show }, > - { "monitor", 1, 2, do_monitor }, > + { "monitor", 1, 3, do_monitor }, > { "snoop", 1, 1, do_snoop }, > { "dump-desc", 1, 1, do_dump_desc }, > { "dump-tables", 1, 1, do_dump_tables }, > -- > 1.7.1 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev