Thanks, I fixed and pushed patch to master. --Pravin.
On Fri, Jan 13, 2012 at 5:17 PM, Ben Pfaff <b...@nicira.com> wrote: > 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