2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-29 13:27:59 +00:00

ofproto: New action TTL decrement.

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. A configuration parameter is added to make TTL
decrement to zero generate packet in.

Feature #8758
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
This commit is contained in:
Pravin B Shelar 2012-01-13 17:54:04 -08:00
parent 444cacf4a7
commit f0fd1a1772
16 changed files with 212 additions and 22 deletions

1
NEWS
View File

@ -8,6 +8,7 @@ v1.5.0 - xx xxx xxxx
- Added support for querying, modifying, and deleting flows - Added support for querying, modifying, and deleting flows
based on flow cookie when using NXM. based on flow cookie when using NXM.
- Added new NXM_PACKET_IN format. - Added new NXM_PACKET_IN format.
- Added new NXAST_DEC_TTL action.
- ovs-ofctl: - ovs-ofctl:
- Added daemonization support to the monitor and snoop commands. - Added daemonization support to the monitor and snoop commands.
- ovs-vsctl: - ovs-vsctl:

View File

@ -361,7 +361,8 @@ enum nx_action_subtype {
NXAST_RESUBMIT_TABLE, /* struct nx_action_resubmit */ NXAST_RESUBMIT_TABLE, /* struct nx_action_resubmit */
NXAST_OUTPUT_REG, /* struct nx_action_output_reg */ NXAST_OUTPUT_REG, /* struct nx_action_output_reg */
NXAST_LEARN, /* struct nx_action_learn */ 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. */ /* Header for Nicira-defined actions. */

View File

@ -136,7 +136,11 @@ enum ofp_config_flags {
OFPC_FRAG_DROP = 1, /* Drop fragments. */ OFPC_FRAG_DROP = 1, /* Drop fragments. */
OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */ OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */
OFPC_FRAG_NX_MATCH = 3, /* Make first fragments available for matching. */ 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. */ /* Switch configuration. */
@ -289,7 +293,8 @@ OFP_ASSERT(sizeof(struct ofp_port_mod) == 32);
/* Why is this packet being sent to the controller? */ /* Why is this packet being sent to the controller? */
enum ofp_packet_in_reason { enum ofp_packet_in_reason {
OFPR_NO_MATCH, /* No matching flow. */ 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). */ /* Packet received on port (datapath -> controller). */

View File

@ -364,6 +364,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
case OFPUTIL_NXAST_EXIT: case OFPUTIL_NXAST_EXIT:
ofputil_put_NXAST_EXIT(b); ofputil_put_NXAST_EXIT(b);
break; break;
case OFPUTIL_NXAST_DEC_TTL:
ofputil_put_NXAST_DEC_TTL(b);
break;
} }
} }

View File

@ -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)"); 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); ds_put_format(string, " (***reason %"PRIu8"***)", pin.reason);
break;
} }
ds_put_format(string, " data_len=%zu", pin.packet_len); 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); learn_format((const struct nx_action_learn *) a, s);
break; break;
case OFPUTIL_NXAST_DEC_TTL:
ds_put_cstr(s, "dec_ttl");
break;
case OFPUTIL_NXAST_EXIT: case OFPUTIL_NXAST_EXIT:
ds_put_cstr(s, "exit"); ds_put_cstr(s, "exit");
break; break;
@ -599,13 +612,18 @@ ofp_print_switch_features(struct ds *string,
static void static void
ofp_print_switch_config(struct ds *string, const struct ofp_switch_config *osc) 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); flags = ntohs(osc->flags);
ds_put_format(string, " frags=%s", ofputil_frag_handling_to_string(flags)); ds_put_format(string, " frags=%s", ofputil_frag_handling_to_string(flags));
flags &= ~OFPC_FRAG_MASK; 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) { if (flags) {
ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags); ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags);
} }

View File

@ -2436,6 +2436,7 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
case OFPUTIL_NXAST_NOTE: case OFPUTIL_NXAST_NOTE:
case OFPUTIL_NXAST_SET_TUNNEL64: case OFPUTIL_NXAST_SET_TUNNEL64:
case OFPUTIL_NXAST_EXIT: case OFPUTIL_NXAST_EXIT:
case OFPUTIL_NXAST_DEC_TTL:
break; break;
} }

View File

@ -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_OUTPUT_REG, nx_action_output_reg, 0, NULL)
NXAST_ACTION(NXAST_LEARN, nx_action_learn, 1, "learn") NXAST_ACTION(NXAST_LEARN, nx_action_learn, 1, "learn")
NXAST_ACTION(NXAST_EXIT, nx_action_header, 0, "exit") NXAST_ACTION(NXAST_EXIT, nx_action_header, 0, "exit")
NXAST_ACTION(NXAST_DEC_TTL, nx_action_header, 0, "dec_ttl")
#undef NXAST_ACTION #undef NXAST_ACTION

View File

@ -227,7 +227,7 @@ struct ofputil_packet_in {
const void *packet; const void *packet;
size_t packet_len; size_t packet_len;
uint8_t reason; /* One of OFPR_*. */ enum ofp_packet_in_reason reason; /* One of OFPRR_*. */
uint8_t table_id; uint8_t table_id;
ovs_be64 cookie; ovs_be64 cookie;

View File

@ -71,6 +71,8 @@ struct ofconn {
/* type == OFCONN_PRIMARY only. */ /* type == OFCONN_PRIMARY only. */
enum nx_role role; /* Role. */ 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. */ struct hmap_node hmap_node; /* In struct connmgr's "controllers" map. */
enum ofproto_band band; /* In-band or out-of-band? */ 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; 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_*. /* Returns the currently configured flow format for 'ofconn', one of NXFF_*.
* *
* The default, if no other format has been set, is NXFF_OPENFLOW10. */ * 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->pktbuf = NULL;
ofconn->miss_send_len = 0; ofconn->miss_send_len = 0;
ofconn->reply_counter = rconn_packet_counter_create (); ofconn->reply_counter = rconn_packet_counter_create ();
ofconn->invalid_ttl_to_controller = false;
return ofconn; return ofconn;
} }
@ -1054,11 +1069,9 @@ ofconn_wait(struct ofconn *ofconn, bool handling_openflow)
/* Returns true if 'ofconn' should receive asynchronous messages. */ /* Returns true if 'ofconn' should receive asynchronous messages. */
static bool static bool
ofconn_receives_async_msgs(const struct ofconn *ofconn) ofconn_receives_async_msgs__(const struct ofconn *ofconn)
{ {
if (!rconn_is_connected(ofconn->rconn)) { if (ofconn->type == OFCONN_PRIMARY) {
return false;
} else if (ofconn->type == OFCONN_PRIMARY) {
/* Primary controllers always get asynchronous messages unless they /* Primary controllers always get asynchronous messages unless they
* have configured themselves as "slaves". */ * have configured themselves as "slaves". */
return ofconn->role != NX_ROLE_SLAVE; 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 /* Returns a human-readable name for an OpenFlow connection between 'mgr' and
* 'target', suitable for use in log messages for identifying the connection. * '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; struct ofconn *ofconn;
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) { 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); schedule_packet_in(ofconn, *pin, flow);
} }
} }

View File

@ -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 *); bool ofconn_get_flow_mod_table_id(const struct ofconn *);
void ofconn_set_flow_mod_table_id(struct ofconn *, bool enable); 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 *); int ofconn_get_miss_send_len(const struct ofconn *);
void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len); void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len);

View File

@ -4291,7 +4291,8 @@ flood_packets(struct action_xlate_ctx *ctx, bool all)
} }
static void 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 ofputil_packet_in pin;
struct ofpbuf *packet; struct ofpbuf *packet;
@ -4336,7 +4337,7 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len)
pin.packet = packet->data; pin.packet = packet->data;
pin.packet_len = packet->size; pin.packet_len = packet->size;
pin.reason = OFPR_ACTION; pin.reason = reason;
pin.table_id = ctx->table_id; pin.table_id = ctx->table_id;
pin.cookie = ctx->cookie; pin.cookie = ctx->cookie;
@ -4349,6 +4350,25 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len)
ofpbuf_delete(packet); 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 static void
xlate_output_action__(struct action_xlate_ctx *ctx, xlate_output_action__(struct action_xlate_ctx *ctx,
uint16_t port, uint16_t max_len) uint16_t port, uint16_t max_len)
@ -4374,7 +4394,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
flood_packets(ctx, true); flood_packets(ctx, true);
break; break;
case OFPP_CONTROLLER: case OFPP_CONTROLLER:
execute_controller_action(ctx, max_len); execute_controller_action(ctx, max_len, OFPR_ACTION);
break; break;
case OFPP_LOCAL: case OFPP_LOCAL:
compose_output_action(ctx, 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; break;
case OFPUTIL_NXAST_DEC_TTL:
if (compose_dec_ttl(ctx)) {
goto out;
}
break;
case OFPUTIL_NXAST_EXIT: case OFPUTIL_NXAST_EXIT:
ctx->exit = true; ctx->exit = true;
break; break;
} }
} }
out:
/* We've let OFPP_NORMAL and the learning action look at the packet, /* We've let OFPP_NORMAL and the learning action look at the packet,
* so drop it now if forwarding is disabled. */ * so drop it now if forwarding is disabled. */
if (port && !stp_forward_in_state(port->stp_state)) { 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: case OFPC_FRAG_NX_MATCH:
/* Nothing to do. */ /* Nothing to do. */
break; break;
case OFPC_INVALID_TTL_TO_CONTROLLER:
NOT_REACHED();
} }
} }

View File

@ -1746,11 +1746,16 @@ handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
{ {
struct ofproto *ofproto = ofconn_get_ofproto(ofconn); struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
struct ofp_switch_config *osc; struct ofp_switch_config *osc;
enum ofp_config_flags flags;
struct ofpbuf *buf; struct ofpbuf *buf;
/* Send reply. */ /* Send reply. */
osc = make_openflow_xid(sizeof *osc, OFPT_GET_CONFIG_REPLY, oh->xid, &buf); 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)); osc->miss_send_len = htons(ofconn_get_miss_send_len(ofconn));
ofconn_send_reply(ofconn, buf); 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)); ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len));

View File

@ -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 \ 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 \ 50 00 02 00 26 e8 00 00 00 00 00 00 00 00 \
"], [0], [dnl "], [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 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 AT_CLEANUP

View File

@ -62,6 +62,38 @@ AT_CHECK([tail -1 stdout], [0],
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP
AT_CLEANUP 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]) AT_SETUP([ofproto-dpif - output, OFPP_NONE ingress port])
OVS_VSWITCHD_START( OVS_VSWITCHD_START(
[add-port br0 p1 -- set Interface p1 type=dummy --\ [add-port br0 p1 -- set Interface p1 type=dummy --\
@ -209,13 +241,13 @@ done
OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl 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 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 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 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 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 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
]) ])

View File

@ -243,7 +243,7 @@ If a switch has no controller configured, or if
the configured controller is disconnected, no traffic is sent, so the configured controller is disconnected, no traffic is sent, so
monitoring will not show any traffic. 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 Connects to \fIswitch\fR and prints to the console all OpenFlow
messages received. Usually, \fIswitch\fR should specify the name of a messages received. Usually, \fIswitch\fR should specify the name of a
bridge in the \fBovs\-vswitchd\fR database. 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 on this argument. (Thus, if \fImiss\-len\fR is not
specified, very little traffic will ordinarily be printed.) specified, very little traffic will ordinarily be printed.)
.IP .IP
.IP
If \fBinvalid_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 This command may be useful for debugging switch or controller
implementations. 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 Restores the queue to the value it was before any \fBset_queue\fR
actions were applied. 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]... .IP \fBnote:\fR[\fIhh\fR]...
Does nothing at all. Any number of bytes represented as hex digits 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 \fIhh\fR may be included. Pairs of hex digits may be separated by

View File

@ -794,6 +794,35 @@ set_packet_in_format(struct vconn *vconn,
ofputil_packet_in_format_to_string(packet_in_format)); 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 static void
monitor_vconn(struct vconn *vconn) monitor_vconn(struct vconn *vconn)
{ {
@ -876,6 +905,11 @@ do_monitor(int argc, char *argv[])
config.miss_send_len = htons(atoi(argv[2])); config.miss_send_len = htons(atoi(argv[2]));
set_switch_config(vconn, &config); set_switch_config(vconn, &config);
} }
if (argc > 3) {
if (!strcmp(argv[3], "invalid_ttl")) {
monitor_set_invalid_ttl_to_controller(vconn);
}
}
monitor_vconn(vconn); monitor_vconn(vconn);
} }
@ -1634,7 +1668,7 @@ do_ofp_print(int argc, char *argv[])
static const struct command all_commands[] = { static const struct command all_commands[] = {
{ "show", 1, 1, do_show }, { "show", 1, 1, do_show },
{ "monitor", 1, 2, do_monitor }, { "monitor", 1, 3, do_monitor },
{ "snoop", 1, 1, do_snoop }, { "snoop", 1, 1, do_snoop },
{ "dump-desc", 1, 1, do_dump_desc }, { "dump-desc", 1, 1, do_dump_desc },
{ "dump-tables", 1, 1, do_dump_tables }, { "dump-tables", 1, 1, do_dump_tables },