Skip to content

Commit a734992

Browse files
committed
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>
1 parent 7c1a76a commit a734992

18 files changed

Lines changed: 254 additions & 23 deletions

DESIGN

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ Second, OFPT_FLOW_REMOVED and NXT_FLOW_REMOVED messages are generated
2424
only if the flow that was removed had the OFPFF_SEND_FLOW_REM flag
2525
set.
2626

27+
Third, OFPT_PACKET_IN and NXT_PACKET_IN messages are sent only to
28+
OpenFlow controller connections that have the correct connection ID
29+
(see "struct nx_controller_id" and "struct nx_action_controller"):
30+
31+
- For packet-in messages generated by a NXAST_CONTROLLER action,
32+
the controller ID specified in the action.
33+
34+
- For other packet-in messages, controller ID zero. (This is the
35+
default ID when an OpenFlow controller does not configure one.)
36+
2737
Finally, Open vSwitch consults a per-connection table indexed by the
2838
message type, reason code, and current role. The following table
2939
shows how this table is initialized by default when an OpenFlow

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ v1.6.0 - xx xxx xxxx
2222
receive asynchronously.
2323
- New "fin_timeout" action.
2424
- Added "fin_timeout" support to "learn" action.
25+
- New Nicira action NXAST_CONTROLLER that offers additional features
26+
over output to OFPP_CONTROLLER.
2527
- The default MAC learning timeout has been increased from 60 seconds
2628
to 300 seconds. The MAC learning timeout is now configurable.
2729
- When QoS settings for an interface do not configure a default queue

include/openflow/nicira-ext.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ enum nicira_type {
116116
NXT_FLOW_AGE = 18,
117117

118118
NXT_SET_ASYNC_CONFIG = 19, /* struct nx_async_config. */
119+
NXT_SET_CONTROLLER_ID = 20, /* struct nx_controller_id. */
119120
};
120121

121122
/* Header for Nicira vendor stats request and reply messages. */
@@ -336,6 +337,7 @@ enum nx_action_subtype {
336337
NXAST_EXIT, /* struct nx_action_header */
337338
NXAST_DEC_TTL, /* struct nx_action_header */
338339
NXAST_FIN_TIMEOUT, /* struct nx_action_fin_timeout */
340+
NXAST_CONTROLLER, /* struct nx_action_controller */
339341
};
340342

341343
/* Header for Nicira-defined actions. */
@@ -1921,5 +1923,45 @@ struct nx_aggregate_stats_reply {
19211923
uint8_t pad[4]; /* Align to 64 bits. */
19221924
};
19231925
OFP_ASSERT(sizeof(struct nx_aggregate_stats_reply) == 48);
1926+
1927+
/* NXT_SET_CONTROLLER_ID.
1928+
*
1929+
* Each OpenFlow controller connection has a 16-bit identifier that is
1930+
* initially 0. This message changes the connection's ID to 'id'.
1931+
*
1932+
* Controller connection IDs need not be unique.
1933+
*
1934+
* The NXAST_CONTROLLER action is the only current user of controller
1935+
* connection IDs. */
1936+
struct nx_controller_id {
1937+
struct nicira_header nxh;
1938+
uint8_t zero[6]; /* Must be zero. */
1939+
ovs_be16 controller_id; /* New controller connection ID. */
1940+
};
1941+
OFP_ASSERT(sizeof(struct nx_controller_id) == 24);
1942+
1943+
/* Action structure for NXAST_CONTROLLER.
1944+
*
1945+
* This generalizes using OFPAT_OUTPUT to send a packet to OFPP_CONTROLLER. In
1946+
* addition to the 'max_len' that OFPAT_OUTPUT supports, it also allows
1947+
* specifying:
1948+
*
1949+
* - 'reason': The reason code to use in the ofp_packet_in or nx_packet_in.
1950+
*
1951+
* - 'controller_id': The ID of the controller connection to which the
1952+
* ofp_packet_in should be sent. The ofp_packet_in or nx_packet_in is
1953+
* sent only to controllers that have the specified controller connection
1954+
* ID. See "struct nx_controller_id" for more information. */
1955+
struct nx_action_controller {
1956+
ovs_be16 type; /* OFPAT_VENDOR. */
1957+
ovs_be16 len; /* Length is 16. */
1958+
ovs_be32 vendor; /* NX_VENDOR_ID. */
1959+
ovs_be16 subtype; /* NXAST_CONTROLLER. */
1960+
ovs_be16 max_len; /* Maximum length to send to controller. */
1961+
ovs_be16 controller_id; /* Controller ID to send packet-in. */
1962+
uint8_t reason; /* enum ofp_packet_in_reason (OFPR_*). */
1963+
uint8_t zero; /* Must be zero. */
1964+
};
1965+
OFP_ASSERT(sizeof(struct nx_action_controller) == 16);
19241966

19251967
#endif /* openflow/nicira-ext.h */

lib/learning-switch.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ lswitch_process_packet(struct lswitch *sw, struct rconn *rconn,
266266
case OFPUTIL_NXT_FLOW_REMOVED:
267267
case OFPUTIL_NXT_FLOW_AGE:
268268
case OFPUTIL_NXT_SET_ASYNC_CONFIG:
269+
case OFPUTIL_NXT_SET_CONTROLLER_ID:
269270
case OFPUTIL_NXST_FLOW_REQUEST:
270271
case OFPUTIL_NXST_AGGREGATE_REQUEST:
271272
case OFPUTIL_NXST_FLOW_REPLY:

lib/ofp-errors.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
2+
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -123,6 +123,9 @@ enum ofperr {
123123
/* NX(1,514). The in_port in an ofp_packet_out request is invalid. */
124124
OFPERR_NXBRC_BAD_IN_PORT,
125125

126+
/* NX(1,515). Must-be-zero field had nonzero value. */
127+
OFPERR_NXBRC_MUST_BE_ZERO,
128+
126129
/* ## ---------------- ## */
127130
/* ## OFPET_BAD_ACTION ## */
128131
/* ## ---------------- ## */
@@ -170,6 +173,9 @@ enum ofperr {
170173
/* OF1.1(2,12). Actions uses an unsupported tag/encap. */
171174
OFPERR_OFPBAC_BAD_TAG,
172175

176+
/* NX(2,256). Must-be-zero action argument had nonzero value. */
177+
OFPERR_NXBAC_MUST_BE_ZERO,
178+
173179
/* ## --------------------- ## */
174180
/* ## OFPET_BAD_INSTRUCTION ## */
175181
/* ## --------------------- ## */

lib/ofp-parse.c

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,48 @@ parse_fin_timeout(struct ofpbuf *b, char *arg)
267267
}
268268
}
269269

270+
static void
271+
parse_controller(struct ofpbuf *b, char *arg)
272+
{
273+
enum ofp_packet_in_reason reason = OFPR_ACTION;
274+
uint16_t controller_id = 0;
275+
uint16_t max_len = UINT16_MAX;
276+
277+
if (!arg[0]) {
278+
/* Use defaults. */
279+
} else if (strspn(arg, "0123456789") == strlen(arg)) {
280+
max_len = str_to_u16(arg, "max_len");
281+
} else {
282+
char *name, *value;
283+
284+
while (ofputil_parse_key_value(&arg, &name, &value)) {
285+
if (!strcmp(name, "reason")) {
286+
if (!ofputil_packet_in_reason_from_string(value, &reason)) {
287+
ovs_fatal(0, "unknown reason \"%s\"", value);
288+
}
289+
} else if (!strcmp(name, "max_len")) {
290+
max_len = str_to_u16(value, "max_len");
291+
} else if (!strcmp(name, "id")) {
292+
controller_id = str_to_u16(value, "id");
293+
} else {
294+
ovs_fatal(0, "unknown key \"%s\" parsing controller action",
295+
name);
296+
}
297+
}
298+
}
299+
300+
if (reason == OFPR_ACTION && controller_id == 0) {
301+
put_output_action(b, OFPP_CONTROLLER)->max_len = htons(max_len);
302+
} else {
303+
struct nx_action_controller *nac;
304+
305+
nac = ofputil_put_NXAST_CONTROLLER(b);
306+
nac->max_len = htons(max_len);
307+
nac->reason = reason;
308+
nac->controller_id = htons(controller_id);
309+
}
310+
}
311+
270312
static void
271313
parse_named_action(enum ofputil_action_code code, const struct flow *flow,
272314
struct ofpbuf *b, char *arg)
@@ -389,6 +431,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
389431
case OFPUTIL_NXAST_FIN_TIMEOUT:
390432
parse_fin_timeout(b, arg);
391433
break;
434+
435+
case OFPUTIL_NXAST_CONTROLLER:
436+
parse_controller(b, arg);
437+
break;
392438
}
393439
}
394440

@@ -418,17 +464,6 @@ str_to_action(const struct flow *flow, char *str, struct ofpbuf *b)
418464
"actions");
419465
}
420466
break;
421-
} else if (!strcasecmp(act, "CONTROLLER")) {
422-
struct ofp_action_output *oao;
423-
oao = put_output_action(b, OFPP_CONTROLLER);
424-
425-
/* Unless a numeric argument is specified, we send the whole
426-
* packet to the controller. */
427-
if (arg[0] && (strspn(arg, "0123456789") == strlen(arg))) {
428-
oao->max_len = htons(str_to_u32(arg));
429-
} else {
430-
oao->max_len = htons(UINT16_MAX);
431-
}
432467
} else if (ofputil_port_from_string(act, &port)) {
433468
put_output_action(b, port);
434469
} else {

lib/ofp-print.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ ofp_print_action(struct ds *s, const union ofp_action *a,
177177
const struct nx_action_autopath *naa;
178178
const struct nx_action_output_reg *naor;
179179
const struct nx_action_fin_timeout *naft;
180+
const struct nx_action_controller *nac;
180181
struct mf_subfield subfield;
181182
uint16_t port;
182183

@@ -354,6 +355,23 @@ ofp_print_action(struct ds *s, const union ofp_action *a,
354355
ds_put_char(s, ')');
355356
break;
356357

358+
case OFPUTIL_NXAST_CONTROLLER:
359+
nac = (const struct nx_action_controller *) a;
360+
ds_put_cstr(s, "controller(");
361+
if (nac->reason != OFPR_ACTION) {
362+
ds_put_format(s, "reason=%s,",
363+
ofputil_packet_in_reason_to_string(nac->reason));
364+
}
365+
if (nac->max_len != htons(UINT16_MAX)) {
366+
ds_put_format(s, "max_len=%"PRIu16",", ntohs(nac->max_len));
367+
}
368+
if (nac->controller_id != htons(0)) {
369+
ds_put_format(s, "id=%"PRIu16",", ntohs(nac->controller_id));
370+
}
371+
ds_chomp(s, ',');
372+
ds_put_char(s, ')');
373+
break;
374+
357375
default:
358376
break;
359377
}
@@ -1391,6 +1409,13 @@ ofp_print_nxt_set_async_config(struct ds *string,
13911409
}
13921410
}
13931411

1412+
static void
1413+
ofp_print_nxt_set_controller_id(struct ds *string,
1414+
const struct nx_controller_id *nci)
1415+
{
1416+
ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
1417+
}
1418+
13941419
static void
13951420
ofp_to_string__(const struct ofp_header *oh,
13961421
const struct ofputil_msg_type *type, struct ds *string,
@@ -1550,6 +1575,10 @@ ofp_to_string__(const struct ofp_header *oh,
15501575
case OFPUTIL_NXT_FLOW_AGE:
15511576
break;
15521577

1578+
case OFPUTIL_NXT_SET_CONTROLLER_ID:
1579+
ofp_print_nxt_set_controller_id(string, msg);
1580+
break;
1581+
15531582
case OFPUTIL_NXT_SET_ASYNC_CONFIG:
15541583
ofp_print_nxt_set_async_config(string, msg);
15551584
break;

lib/ofp-util.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,10 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length,
404404
{ OFPUTIL_NXT_SET_ASYNC_CONFIG, OFP10_VERSION,
405405
NXT_SET_ASYNC_CONFIG, "NXT_SET_ASYNC_CONFIG",
406406
sizeof(struct nx_async_config), 0 },
407+
408+
{ OFPUTIL_NXT_SET_CONTROLLER_ID, OFP10_VERSION,
409+
NXT_SET_CONTROLLER_ID, "NXT_SET_CONTROLLER_ID",
410+
sizeof(struct nx_controller_id), 0 },
407411
};
408412

409413
static const struct ofputil_msg_category nxt_category = {
@@ -2527,6 +2531,12 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
25272531
error = learn_check((const struct nx_action_learn *) a, flow);
25282532
break;
25292533

2534+
case OFPUTIL_NXAST_CONTROLLER:
2535+
if (((const struct nx_action_controller *) a)->zero) {
2536+
error = OFPERR_NXBAC_MUST_BE_ZERO;
2537+
}
2538+
break;
2539+
25302540
case OFPUTIL_OFPAT_STRIP_VLAN:
25312541
case OFPUTIL_OFPAT_SET_NW_SRC:
25322542
case OFPUTIL_OFPAT_SET_NW_DST:

lib/ofp-util.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ NXAST_ACTION(NXAST_LEARN, nx_action_learn, 1, "learn")
3838
NXAST_ACTION(NXAST_EXIT, nx_action_header, 0, "exit")
3939
NXAST_ACTION(NXAST_DEC_TTL, nx_action_header, 0, "dec_ttl")
4040
NXAST_ACTION(NXAST_FIN_TIMEOUT, nx_action_fin_timeout, 0, "fin_timeout")
41+
NXAST_ACTION(NXAST_CONTROLLER, nx_action_controller, 0, "controller")
4142
#undef NXAST_ACTION

lib/ofp-util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ enum ofputil_msg_code {
8181
OFPUTIL_NXT_PACKET_IN,
8282
OFPUTIL_NXT_FLOW_AGE,
8383
OFPUTIL_NXT_SET_ASYNC_CONFIG,
84+
OFPUTIL_NXT_SET_CONTROLLER_ID,
8485

8586
/* NXST_* stat requests. */
8687
OFPUTIL_NXST_FLOW_REQUEST,
@@ -233,6 +234,7 @@ struct ofputil_packet_in {
233234
size_t packet_len;
234235

235236
enum ofp_packet_in_reason reason; /* One of OFPRR_*. */
237+
uint16_t controller_id; /* Controller ID to send to. */
236238
uint8_t table_id;
237239
ovs_be64 cookie;
238240

0 commit comments

Comments
 (0)