mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
Add ability to direct "packet-in"s to particular controllers.
Nicira's controllers are somewhat heterogeneous, so that particular "packet-in" messages should be directed to particular controllers. This new Nicira extension action allows designating a controller or controllers to receive the "packet-in" using a 16-bit integer ID. The new NXAST_CONTROLLER action also specifies the "reason" code to include in the "packet-in" message. This is particularly useful for simulating a "no-match" "packet-in" using a rule. Feature #8946. Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
parent
7c1a76a467
commit
a7349929fb
10
DESIGN
10
DESIGN
@ -24,6 +24,16 @@ Second, OFPT_FLOW_REMOVED and NXT_FLOW_REMOVED messages are generated
|
||||
only if the flow that was removed had the OFPFF_SEND_FLOW_REM flag
|
||||
set.
|
||||
|
||||
Third, OFPT_PACKET_IN and NXT_PACKET_IN messages are sent only to
|
||||
OpenFlow controller connections that have the correct connection ID
|
||||
(see "struct nx_controller_id" and "struct nx_action_controller"):
|
||||
|
||||
- For packet-in messages generated by a NXAST_CONTROLLER action,
|
||||
the controller ID specified in the action.
|
||||
|
||||
- For other packet-in messages, controller ID zero. (This is the
|
||||
default ID when an OpenFlow controller does not configure one.)
|
||||
|
||||
Finally, Open vSwitch consults a per-connection table indexed by the
|
||||
message type, reason code, and current role. The following table
|
||||
shows how this table is initialized by default when an OpenFlow
|
||||
|
2
NEWS
2
NEWS
@ -22,6 +22,8 @@ v1.6.0 - xx xxx xxxx
|
||||
receive asynchronously.
|
||||
- New "fin_timeout" action.
|
||||
- Added "fin_timeout" support to "learn" action.
|
||||
- New Nicira action NXAST_CONTROLLER that offers additional features
|
||||
over output to OFPP_CONTROLLER.
|
||||
- The default MAC learning timeout has been increased from 60 seconds
|
||||
to 300 seconds. The MAC learning timeout is now configurable.
|
||||
- When QoS settings for an interface do not configure a default queue
|
||||
|
@ -116,6 +116,7 @@ enum nicira_type {
|
||||
NXT_FLOW_AGE = 18,
|
||||
|
||||
NXT_SET_ASYNC_CONFIG = 19, /* struct nx_async_config. */
|
||||
NXT_SET_CONTROLLER_ID = 20, /* struct nx_controller_id. */
|
||||
};
|
||||
|
||||
/* Header for Nicira vendor stats request and reply messages. */
|
||||
@ -336,6 +337,7 @@ enum nx_action_subtype {
|
||||
NXAST_EXIT, /* struct nx_action_header */
|
||||
NXAST_DEC_TTL, /* struct nx_action_header */
|
||||
NXAST_FIN_TIMEOUT, /* struct nx_action_fin_timeout */
|
||||
NXAST_CONTROLLER, /* struct nx_action_controller */
|
||||
};
|
||||
|
||||
/* Header for Nicira-defined actions. */
|
||||
@ -1921,5 +1923,45 @@ struct nx_aggregate_stats_reply {
|
||||
uint8_t pad[4]; /* Align to 64 bits. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_aggregate_stats_reply) == 48);
|
||||
|
||||
/* NXT_SET_CONTROLLER_ID.
|
||||
*
|
||||
* Each OpenFlow controller connection has a 16-bit identifier that is
|
||||
* initially 0. This message changes the connection's ID to 'id'.
|
||||
*
|
||||
* Controller connection IDs need not be unique.
|
||||
*
|
||||
* The NXAST_CONTROLLER action is the only current user of controller
|
||||
* connection IDs. */
|
||||
struct nx_controller_id {
|
||||
struct nicira_header nxh;
|
||||
uint8_t zero[6]; /* Must be zero. */
|
||||
ovs_be16 controller_id; /* New controller connection ID. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_controller_id) == 24);
|
||||
|
||||
/* Action structure for NXAST_CONTROLLER.
|
||||
*
|
||||
* This generalizes using OFPAT_OUTPUT to send a packet to OFPP_CONTROLLER. In
|
||||
* addition to the 'max_len' that OFPAT_OUTPUT supports, it also allows
|
||||
* specifying:
|
||||
*
|
||||
* - 'reason': The reason code to use in the ofp_packet_in or nx_packet_in.
|
||||
*
|
||||
* - 'controller_id': The ID of the controller connection to which the
|
||||
* ofp_packet_in should be sent. The ofp_packet_in or nx_packet_in is
|
||||
* sent only to controllers that have the specified controller connection
|
||||
* ID. See "struct nx_controller_id" for more information. */
|
||||
struct nx_action_controller {
|
||||
ovs_be16 type; /* OFPAT_VENDOR. */
|
||||
ovs_be16 len; /* Length is 16. */
|
||||
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
||||
ovs_be16 subtype; /* NXAST_CONTROLLER. */
|
||||
ovs_be16 max_len; /* Maximum length to send to controller. */
|
||||
ovs_be16 controller_id; /* Controller ID to send packet-in. */
|
||||
uint8_t reason; /* enum ofp_packet_in_reason (OFPR_*). */
|
||||
uint8_t zero; /* Must be zero. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_action_controller) == 16);
|
||||
|
||||
#endif /* openflow/nicira-ext.h */
|
||||
|
@ -266,6 +266,7 @@ lswitch_process_packet(struct lswitch *sw, struct rconn *rconn,
|
||||
case OFPUTIL_NXT_FLOW_REMOVED:
|
||||
case OFPUTIL_NXT_FLOW_AGE:
|
||||
case OFPUTIL_NXT_SET_ASYNC_CONFIG:
|
||||
case OFPUTIL_NXT_SET_CONTROLLER_ID:
|
||||
case OFPUTIL_NXST_FLOW_REQUEST:
|
||||
case OFPUTIL_NXST_AGGREGATE_REQUEST:
|
||||
case OFPUTIL_NXST_FLOW_REPLY:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -123,6 +123,9 @@ enum ofperr {
|
||||
/* NX(1,514). The in_port in an ofp_packet_out request is invalid. */
|
||||
OFPERR_NXBRC_BAD_IN_PORT,
|
||||
|
||||
/* NX(1,515). Must-be-zero field had nonzero value. */
|
||||
OFPERR_NXBRC_MUST_BE_ZERO,
|
||||
|
||||
/* ## ---------------- ## */
|
||||
/* ## OFPET_BAD_ACTION ## */
|
||||
/* ## ---------------- ## */
|
||||
@ -170,6 +173,9 @@ enum ofperr {
|
||||
/* OF1.1(2,12). Actions uses an unsupported tag/encap. */
|
||||
OFPERR_OFPBAC_BAD_TAG,
|
||||
|
||||
/* NX(2,256). Must-be-zero action argument had nonzero value. */
|
||||
OFPERR_NXBAC_MUST_BE_ZERO,
|
||||
|
||||
/* ## --------------------- ## */
|
||||
/* ## OFPET_BAD_INSTRUCTION ## */
|
||||
/* ## --------------------- ## */
|
||||
|
@ -267,6 +267,48 @@ parse_fin_timeout(struct ofpbuf *b, char *arg)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_controller(struct ofpbuf *b, char *arg)
|
||||
{
|
||||
enum ofp_packet_in_reason reason = OFPR_ACTION;
|
||||
uint16_t controller_id = 0;
|
||||
uint16_t max_len = UINT16_MAX;
|
||||
|
||||
if (!arg[0]) {
|
||||
/* Use defaults. */
|
||||
} else if (strspn(arg, "0123456789") == strlen(arg)) {
|
||||
max_len = str_to_u16(arg, "max_len");
|
||||
} else {
|
||||
char *name, *value;
|
||||
|
||||
while (ofputil_parse_key_value(&arg, &name, &value)) {
|
||||
if (!strcmp(name, "reason")) {
|
||||
if (!ofputil_packet_in_reason_from_string(value, &reason)) {
|
||||
ovs_fatal(0, "unknown reason \"%s\"", value);
|
||||
}
|
||||
} else if (!strcmp(name, "max_len")) {
|
||||
max_len = str_to_u16(value, "max_len");
|
||||
} else if (!strcmp(name, "id")) {
|
||||
controller_id = str_to_u16(value, "id");
|
||||
} else {
|
||||
ovs_fatal(0, "unknown key \"%s\" parsing controller action",
|
||||
name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reason == OFPR_ACTION && controller_id == 0) {
|
||||
put_output_action(b, OFPP_CONTROLLER)->max_len = htons(max_len);
|
||||
} else {
|
||||
struct nx_action_controller *nac;
|
||||
|
||||
nac = ofputil_put_NXAST_CONTROLLER(b);
|
||||
nac->max_len = htons(max_len);
|
||||
nac->reason = reason;
|
||||
nac->controller_id = htons(controller_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_named_action(enum ofputil_action_code code, const struct flow *flow,
|
||||
struct ofpbuf *b, char *arg)
|
||||
@ -389,6 +431,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
|
||||
case OFPUTIL_NXAST_FIN_TIMEOUT:
|
||||
parse_fin_timeout(b, arg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXAST_CONTROLLER:
|
||||
parse_controller(b, arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,17 +464,6 @@ str_to_action(const struct flow *flow, char *str, struct ofpbuf *b)
|
||||
"actions");
|
||||
}
|
||||
break;
|
||||
} else if (!strcasecmp(act, "CONTROLLER")) {
|
||||
struct ofp_action_output *oao;
|
||||
oao = put_output_action(b, OFPP_CONTROLLER);
|
||||
|
||||
/* Unless a numeric argument is specified, we send the whole
|
||||
* packet to the controller. */
|
||||
if (arg[0] && (strspn(arg, "0123456789") == strlen(arg))) {
|
||||
oao->max_len = htons(str_to_u32(arg));
|
||||
} else {
|
||||
oao->max_len = htons(UINT16_MAX);
|
||||
}
|
||||
} else if (ofputil_port_from_string(act, &port)) {
|
||||
put_output_action(b, port);
|
||||
} else {
|
||||
|
@ -177,6 +177,7 @@ ofp_print_action(struct ds *s, const union ofp_action *a,
|
||||
const struct nx_action_autopath *naa;
|
||||
const struct nx_action_output_reg *naor;
|
||||
const struct nx_action_fin_timeout *naft;
|
||||
const struct nx_action_controller *nac;
|
||||
struct mf_subfield subfield;
|
||||
uint16_t port;
|
||||
|
||||
@ -354,6 +355,23 @@ ofp_print_action(struct ds *s, const union ofp_action *a,
|
||||
ds_put_char(s, ')');
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXAST_CONTROLLER:
|
||||
nac = (const struct nx_action_controller *) a;
|
||||
ds_put_cstr(s, "controller(");
|
||||
if (nac->reason != OFPR_ACTION) {
|
||||
ds_put_format(s, "reason=%s,",
|
||||
ofputil_packet_in_reason_to_string(nac->reason));
|
||||
}
|
||||
if (nac->max_len != htons(UINT16_MAX)) {
|
||||
ds_put_format(s, "max_len=%"PRIu16",", ntohs(nac->max_len));
|
||||
}
|
||||
if (nac->controller_id != htons(0)) {
|
||||
ds_put_format(s, "id=%"PRIu16",", ntohs(nac->controller_id));
|
||||
}
|
||||
ds_chomp(s, ',');
|
||||
ds_put_char(s, ')');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1391,6 +1409,13 @@ ofp_print_nxt_set_async_config(struct ds *string,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_nxt_set_controller_id(struct ds *string,
|
||||
const struct nx_controller_id *nci)
|
||||
{
|
||||
ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_to_string__(const struct ofp_header *oh,
|
||||
const struct ofputil_msg_type *type, struct ds *string,
|
||||
@ -1550,6 +1575,10 @@ ofp_to_string__(const struct ofp_header *oh,
|
||||
case OFPUTIL_NXT_FLOW_AGE:
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXT_SET_CONTROLLER_ID:
|
||||
ofp_print_nxt_set_controller_id(string, msg);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXT_SET_ASYNC_CONFIG:
|
||||
ofp_print_nxt_set_async_config(string, msg);
|
||||
break;
|
||||
|
@ -404,6 +404,10 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
|
||||
{ OFPUTIL_NXT_SET_ASYNC_CONFIG, OFP10_VERSION,
|
||||
NXT_SET_ASYNC_CONFIG, "NXT_SET_ASYNC_CONFIG",
|
||||
sizeof(struct nx_async_config), 0 },
|
||||
|
||||
{ OFPUTIL_NXT_SET_CONTROLLER_ID, OFP10_VERSION,
|
||||
NXT_SET_CONTROLLER_ID, "NXT_SET_CONTROLLER_ID",
|
||||
sizeof(struct nx_controller_id), 0 },
|
||||
};
|
||||
|
||||
static const struct ofputil_msg_category nxt_category = {
|
||||
@ -2527,6 +2531,12 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
|
||||
error = learn_check((const struct nx_action_learn *) a, flow);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXAST_CONTROLLER:
|
||||
if (((const struct nx_action_controller *) a)->zero) {
|
||||
error = OFPERR_NXBAC_MUST_BE_ZERO;
|
||||
}
|
||||
break;
|
||||
|
||||
case OFPUTIL_OFPAT_STRIP_VLAN:
|
||||
case OFPUTIL_OFPAT_SET_NW_SRC:
|
||||
case OFPUTIL_OFPAT_SET_NW_DST:
|
||||
|
@ -38,4 +38,5 @@ 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")
|
||||
NXAST_ACTION(NXAST_FIN_TIMEOUT, nx_action_fin_timeout, 0, "fin_timeout")
|
||||
NXAST_ACTION(NXAST_CONTROLLER, nx_action_controller, 0, "controller")
|
||||
#undef NXAST_ACTION
|
||||
|
@ -81,6 +81,7 @@ enum ofputil_msg_code {
|
||||
OFPUTIL_NXT_PACKET_IN,
|
||||
OFPUTIL_NXT_FLOW_AGE,
|
||||
OFPUTIL_NXT_SET_ASYNC_CONFIG,
|
||||
OFPUTIL_NXT_SET_CONTROLLER_ID,
|
||||
|
||||
/* NXST_* stat requests. */
|
||||
OFPUTIL_NXST_FLOW_REQUEST,
|
||||
@ -233,6 +234,7 @@ struct ofputil_packet_in {
|
||||
size_t packet_len;
|
||||
|
||||
enum ofp_packet_in_reason reason; /* One of OFPRR_*. */
|
||||
uint16_t controller_id; /* Controller ID to send to. */
|
||||
uint8_t table_id;
|
||||
ovs_be64 cookie;
|
||||
|
||||
|
@ -73,6 +73,7 @@ struct ofconn {
|
||||
struct pinsched *schedulers[N_SCHEDULERS];
|
||||
struct pktbuf *pktbuf; /* OpenFlow packet buffers. */
|
||||
int miss_send_len; /* Bytes to send of buffered packets. */
|
||||
uint16_t controller_id; /* Connection controller ID. */
|
||||
|
||||
/* Number of OpenFlow messages queued on 'rconn' as replies to OpenFlow
|
||||
* requests, and the maximum number before we stop reading OpenFlow
|
||||
@ -820,6 +821,16 @@ ofconn_set_packet_in_format(struct ofconn *ofconn,
|
||||
ofconn->packet_in_format = packet_in_format;
|
||||
}
|
||||
|
||||
/* Sets the controller connection ID for 'ofconn' to 'controller_id'.
|
||||
*
|
||||
* The connection controller ID is used for OFPP_CONTROLLER and
|
||||
* NXAST_CONTROLLER actions. See "struct nx_action_controller" for details. */
|
||||
void
|
||||
ofconn_set_controller_id(struct ofconn *ofconn, uint16_t controller_id)
|
||||
{
|
||||
ofconn->controller_id = controller_id;
|
||||
}
|
||||
|
||||
/* Returns true if the NXT_FLOW_MOD_TABLE_ID extension is enabled, false
|
||||
* otherwise.
|
||||
*
|
||||
@ -1017,6 +1028,7 @@ ofconn_flush(struct ofconn *ofconn)
|
||||
ofconn->miss_send_len = (ofconn->type == OFCONN_PRIMARY
|
||||
? OFP_DEFAULT_MISS_SEND_LEN
|
||||
: 0);
|
||||
ofconn->controller_id = 0;
|
||||
|
||||
rconn_packet_counter_destroy(ofconn->reply_counter);
|
||||
ofconn->reply_counter = rconn_packet_counter_create();
|
||||
@ -1292,7 +1304,8 @@ connmgr_send_packet_in(struct connmgr *mgr,
|
||||
struct ofconn *ofconn;
|
||||
|
||||
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
|
||||
if (ofconn_receives_async_msg(ofconn, OAM_PACKET_IN, pin->reason)) {
|
||||
if (ofconn_receives_async_msg(ofconn, OAM_PACKET_IN, pin->reason)
|
||||
&& ofconn->controller_id == pin->controller_id) {
|
||||
schedule_packet_in(ofconn, *pin, flow);
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ void ofconn_set_flow_format(struct ofconn *, enum nx_flow_format);
|
||||
enum nx_packet_in_format ofconn_get_packet_in_format(struct ofconn *);
|
||||
void ofconn_set_packet_in_format(struct ofconn *, enum nx_packet_in_format);
|
||||
|
||||
void ofconn_set_controller_id(struct ofconn *, uint16_t controller_id);
|
||||
|
||||
bool ofconn_get_flow_mod_table_id(const struct ofconn *);
|
||||
void ofconn_set_flow_mod_table_id(struct ofconn *, bool enable);
|
||||
|
||||
|
@ -2456,6 +2456,7 @@ send_packet_in_miss(struct ofproto_dpif *ofproto, const struct ofpbuf *packet,
|
||||
pin.packet_len = packet->size;
|
||||
pin.total_len = packet->size;
|
||||
pin.reason = OFPR_NO_MATCH;
|
||||
pin.controller_id = 0;
|
||||
|
||||
pin.table_id = 0;
|
||||
pin.cookie = 0;
|
||||
@ -4465,7 +4466,8 @@ flood_packets(struct action_xlate_ctx *ctx, bool all)
|
||||
|
||||
static void
|
||||
execute_controller_action(struct action_xlate_ctx *ctx, int len,
|
||||
enum ofp_packet_in_reason reason)
|
||||
enum ofp_packet_in_reason reason,
|
||||
uint16_t controller_id)
|
||||
{
|
||||
struct ofputil_packet_in pin;
|
||||
struct ofpbuf *packet;
|
||||
@ -4511,6 +4513,7 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len,
|
||||
pin.packet = packet->data;
|
||||
pin.packet_len = packet->size;
|
||||
pin.reason = reason;
|
||||
pin.controller_id = controller_id;
|
||||
pin.table_id = ctx->table_id;
|
||||
pin.cookie = ctx->rule ? ctx->rule->up.flow_cookie : 0;
|
||||
|
||||
@ -4535,7 +4538,7 @@ compose_dec_ttl(struct action_xlate_ctx *ctx)
|
||||
ctx->flow.nw_ttl--;
|
||||
return false;
|
||||
} else {
|
||||
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL);
|
||||
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0);
|
||||
|
||||
/* Stop processing for current table. */
|
||||
return true;
|
||||
@ -4567,7 +4570,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
|
||||
flood_packets(ctx, true);
|
||||
break;
|
||||
case OFPP_CONTROLLER:
|
||||
execute_controller_action(ctx, max_len, OFPR_ACTION);
|
||||
execute_controller_action(ctx, max_len, OFPR_ACTION, 0);
|
||||
break;
|
||||
case OFPP_NONE:
|
||||
break;
|
||||
@ -4805,6 +4808,7 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
|
||||
const struct nx_action_autopath *naa;
|
||||
const struct nx_action_bundle *nab;
|
||||
const struct nx_action_output_reg *naor;
|
||||
const struct nx_action_controller *nac;
|
||||
enum ofputil_action_code code;
|
||||
ovs_be64 tun_id;
|
||||
|
||||
@ -4965,6 +4969,12 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
|
||||
ctx->has_fin_timeout = true;
|
||||
xlate_fin_timeout(ctx, (const struct nx_action_fin_timeout *) ia);
|
||||
break;
|
||||
|
||||
case OFPUTIL_NXAST_CONTROLLER:
|
||||
nac = (const struct nx_action_controller *) ia;
|
||||
execute_controller_action(ctx, ntohs(nac->max_len), nac->reason,
|
||||
ntohs(nac->controller_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3137,6 +3137,21 @@ handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
handle_nxt_set_controller_id(struct ofconn *ofconn,
|
||||
const struct ofp_header *oh)
|
||||
{
|
||||
const struct nx_controller_id *nci;
|
||||
|
||||
nci = (const struct nx_controller_id *) oh;
|
||||
if (!is_all_zeros(nci->zero, sizeof nci->zero)) {
|
||||
return OFPERR_NXBRC_MUST_BE_ZERO;
|
||||
}
|
||||
|
||||
ofconn_set_controller_id(ofconn, ntohs(nci->controller_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||
{
|
||||
@ -3207,6 +3222,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
|
||||
case OFPUTIL_NXT_SET_PACKET_IN_FORMAT:
|
||||
return handle_nxt_set_packet_in_format(ofconn, oh);
|
||||
|
||||
case OFPUTIL_NXT_SET_CONTROLLER_ID:
|
||||
return handle_nxt_set_controller_id(ofconn, oh);
|
||||
|
||||
case OFPUTIL_NXT_FLOW_MOD:
|
||||
return handle_flow_mod(ofconn, oh);
|
||||
|
||||
|
@ -728,6 +728,16 @@ NXT_SET_ASYNC_CONFIG (xid=0x0):
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([NXT_SET_CONTROLLER_ID])
|
||||
AT_KEYWORDS([ofp-print])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
01 04 00 18 00 00 00 03 00 00 23 20 00 00 00 14 \
|
||||
00 00 00 00 00 00 00 7b \
|
||||
"], [0], [dnl
|
||||
NXT_SET_CONTROLLER_ID (xid=0x3): id=123
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([NXT_SET_FLOW_FORMAT])
|
||||
AT_KEYWORDS([ofp-print])
|
||||
AT_CHECK([ovs-ofctl ofp-print "\
|
||||
|
@ -433,14 +433,21 @@ check_async () {
|
||||
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
|
||||
: > expout
|
||||
|
||||
# OFPT_PACKET_IN, OFPR_ACTION
|
||||
# OFPT_PACKET_IN, OFPR_ACTION (controller_id=0)
|
||||
ovs-ofctl -v packet-out br0 none controller '0001020304050010203040501234'
|
||||
if test X"$1" = X"OFPR_ACTION"; then shift;
|
||||
echo >>expout "OFPT_PACKET_IN: total_len=14 in_port=NONE (via action) data_len=14 (unbuffered)
|
||||
priority:0,tunnel:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0)"
|
||||
fi
|
||||
|
||||
# OFPT_PACKET_IN, OFPR_INVALID_TTL
|
||||
# OFPT_PACKET_IN, OFPR_NO_MATCH (controller_id=123)
|
||||
ovs-ofctl -v packet-out br0 none 'controller(reason=no_match,id=123)' '0001020304050010203040501234'
|
||||
if test X"$1" = X"OFPR_NO_MATCH"; then shift;
|
||||
echo >>expout "OFPT_PACKET_IN: total_len=14 in_port=NONE (via no_match) data_len=14 (unbuffered)
|
||||
priority:0,tunnel:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0)"
|
||||
fi
|
||||
|
||||
# OFPT_PACKET_IN, OFPR_INVALID_TTL (controller_id=0)
|
||||
ovs-ofctl packet-out br0 none dec_ttl '002583dfb4000026b98cb0f908004500003fb7e200000011339bac11370dac100002d7730035002b8f6d86fb0100000100000000000006626c702d7873066e696369726103636f6d00000f00'
|
||||
if test X"$1" = X"OFPR_INVALID_TTL"; then shift;
|
||||
echo >>expout "OFPT_PACKET_IN: total_len=76 in_port=NONE (via invalid_ttl) data_len=76 (unbuffered)
|
||||
@ -502,9 +509,16 @@ check_async 4 OFPPR_ADD OFPPR_DELETE
|
||||
ovs-appctl -t ovs-ofctl ofctl/send 01040028000000020000232000000013000000020000000500000005000000020000000200000005
|
||||
check_async 5 OFPR_INVALID_TTL OFPPR_DELETE OFPRR_DELETE
|
||||
|
||||
# Set controller ID 123.
|
||||
ovs-appctl -t ovs-ofctl ofctl/send 01040018000000030000232000000014000000000000007b
|
||||
check_async 6 OFPR_NO_MATCH OFPPR_DELETE OFPRR_DELETE
|
||||
|
||||
# Restore controller ID 0.
|
||||
ovs-appctl -t ovs-ofctl ofctl/send 010400180000000300002320000000140000000000000000
|
||||
|
||||
# Become master.
|
||||
ovs-appctl -t ovs-ofctl ofctl/send 0104001400000002000023200000000a00000001
|
||||
check_async 6 OFPR_ACTION OFPPR_ADD
|
||||
check_async 7 OFPR_ACTION OFPPR_ADD
|
||||
|
||||
ovs-appctl -t ovs-ofctl exit
|
||||
AT_CLEANUP
|
||||
|
@ -28,6 +28,7 @@ actions=resubmit:1,resubmit(2),resubmit(,3),resubmit(2,3)
|
||||
send_flow_rem,actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
|
||||
check_overlap,actions=output:1,exit,output:2
|
||||
actions=fin_timeout(idle_timeout=5,hard_timeout=15)
|
||||
actions=controller(max_len=123,reason=invalid_ttl,id=555)
|
||||
]])
|
||||
|
||||
AT_CHECK([ovs-ofctl parse-flows flows.txt
|
||||
@ -60,6 +61,7 @@ NXT_FLOW_MOD: ADD table:255 actions=resubmit:1,resubmit:2,resubmit(,3),resubmit(
|
||||
NXT_FLOW_MOD: ADD table:255 send_flow_rem actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
|
||||
NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
|
||||
NXT_FLOW_MOD: ADD table:255 actions=fin_timeout(idle_timeout=5,hard_timeout=15)
|
||||
NXT_FLOW_MOD: ADD table:255 actions=controller(reason=invalid_ttl,max_len=123,id=555)
|
||||
]])
|
||||
AT_CLEANUP
|
||||
|
||||
|
@ -756,11 +756,35 @@ tree protocol).
|
||||
Outputs the packet on all switch physical ports other than the port on
|
||||
which it was received.
|
||||
.
|
||||
.IP \fBcontroller\fR:\fImax_len\fR
|
||||
.IP \fBcontroller(\fIkey\fB=\fIvalue\fR...\fB)
|
||||
Sends the packet to the OpenFlow controller as a ``packet in''
|
||||
message. If \fImax_len\fR is a number, then it specifies the maximum
|
||||
number of bytes that should be sent. If \fImax_len\fR is \fBALL\fR or
|
||||
omitted, then the entire packet is sent.
|
||||
message. The supported key-value pairs are:
|
||||
.RS
|
||||
.IP "\fBmax_len=\fInbytes\fR"
|
||||
Limit to \fInbytes\fR the number of bytes of the packet to send to
|
||||
the controller. By default the entire packet is sent.
|
||||
.IP "\fBreason=\fIreason\fR"
|
||||
Specify \fIreason\fR as the reason for sending the message in the
|
||||
``packet in'' message. The supported reasons are \fBaction\fR (the
|
||||
default), \fBno_match\fR, and \fBinvalid_ttl\fR.
|
||||
.IP "\fBid=\fIcontroller-id\fR"
|
||||
Specify \fIcontroller-id\fR, a 16-bit integer, as the connection ID of
|
||||
the OpenFlow controller or controllers to which the ``packet in''
|
||||
message should be sent. The default is zero. Zero is also the
|
||||
default connection ID for each controller connection, and a given
|
||||
controller connection will only have a nonzero connection ID if its
|
||||
controller uses the \fBNXT_SET_CONTROLLER_ID\fR Nicira extension to
|
||||
OpenFlow.
|
||||
.RE
|
||||
Any \fIreason\fR other than \fBaction\fR and any nonzero
|
||||
\fIcontroller-id\fR uses a Nicira vendor extension that, as of this
|
||||
writing, is only known to be implemented by Open vSwitch (version 1.6
|
||||
or later).
|
||||
.
|
||||
.IP \fBcontroller\fR
|
||||
.IQ \fBcontroller\fR[\fB:\fInbytes\fR]
|
||||
Shorthand for \fBcontroller()\fR or
|
||||
\fBcontroller(max_len=\fInbytes\fB)\fR, respectively.
|
||||
.
|
||||
.IP \fBlocal\fR
|
||||
Outputs the packet on the ``local port,'' which corresponds to the
|
||||
|
Loading…
x
Reference in New Issue
Block a user