[ovs-dev] [PATCH v3] ofproto: New action TTL decrement.
Ben Pfaff
blp at nicira.com
Sat Jan 14 01:17:06 UTC 2012
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 at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
More information about the dev
mailing list