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:
parent
444cacf4a7
commit
f0fd1a1772
1
NEWS
1
NEWS
@ -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:
|
||||||
|
@ -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. */
|
||||||
|
@ -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). */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user