mirror of
https://github.com/openvswitch/ovs
synced 2025-08-29 05:18:13 +00:00
Implement OFPT_TABLE_STATUS Message.
On change in a table state, the controller needs to be informed with the OFPT_TABLE_STATUS message. The message is sent with reason OFPTR_VACANCY_DOWN or OFPTR_VACANCY_UP in case of change in remaining space eventually crossing any one of the threshold. Signed-off-by: Saloni Jain <saloni.jain@tcs.com> Co-authored-by: Rishi Bamba <rishi.bamba@tcs.com> Signed-off-by: Rishi Bamba <rishi.bamba@tcs.com> [blp@ovn.org added vacancy event initialization and tests and updated NEWS] Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
parent
1478295a21
commit
6c6eedc5d6
1
NEWS
1
NEWS
@ -5,6 +5,7 @@ Post-v2.5.0
|
|||||||
- OpenFlow:
|
- OpenFlow:
|
||||||
* OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
|
* OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
|
||||||
* OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported.
|
* OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported.
|
||||||
|
* OpenFlow 1.4+ OFPT_TABLE_STATUS is now supported.
|
||||||
* New property-based packet-in message format NXT_PACKET_IN2 with support
|
* New property-based packet-in message format NXT_PACKET_IN2 with support
|
||||||
for arbitrary user-provided data and for serializing flow table
|
for arbitrary user-provided data and for serializing flow table
|
||||||
traversal into a continuation for later resumption.
|
traversal into a continuation for later resumption.
|
||||||
|
@ -157,6 +157,14 @@ struct ofp14_table_desc {
|
|||||||
};
|
};
|
||||||
OFP_ASSERT(sizeof(struct ofp14_table_desc) == 8);
|
OFP_ASSERT(sizeof(struct ofp14_table_desc) == 8);
|
||||||
|
|
||||||
|
/* A table config has changed in the datapath */
|
||||||
|
struct ofp14_table_status {
|
||||||
|
uint8_t reason; /* One of OFPTR_*. */
|
||||||
|
uint8_t pad[7]; /* Pad to 64 bits */
|
||||||
|
/* Followed by struct ofp14_table_desc */
|
||||||
|
};
|
||||||
|
OFP_ASSERT(sizeof(struct ofp14_table_status) == 8);
|
||||||
|
|
||||||
/* ## ---------------- ## */
|
/* ## ---------------- ## */
|
||||||
/* ## ofp14_port_stats ## */
|
/* ## ofp14_port_stats ## */
|
||||||
/* ## ---------------- ## */
|
/* ## ---------------- ## */
|
||||||
|
@ -256,6 +256,9 @@ enum ofpraw {
|
|||||||
/* OFPT 1.4+ (30): struct ofp14_role_status, uint8_t[8][]. */
|
/* OFPT 1.4+ (30): struct ofp14_role_status, uint8_t[8][]. */
|
||||||
OFPRAW_OFPT14_ROLE_STATUS,
|
OFPRAW_OFPT14_ROLE_STATUS,
|
||||||
|
|
||||||
|
/* OFPT 1.4+ (31): struct ofp14_table_status, uint8_t[8][]. */
|
||||||
|
OFPRAW_OFPT14_TABLE_STATUS,
|
||||||
|
|
||||||
/* OFPT 1.4+ (32): struct ofp14_requestforward, uint8_t[8][]. */
|
/* OFPT 1.4+ (32): struct ofp14_requestforward, uint8_t[8][]. */
|
||||||
OFPRAW_OFPT14_REQUESTFORWARD,
|
OFPRAW_OFPT14_REQUESTFORWARD,
|
||||||
|
|
||||||
@ -586,6 +589,9 @@ enum ofptype {
|
|||||||
/* Request forwarding by the switch. */
|
/* Request forwarding by the switch. */
|
||||||
OFPTYPE_REQUESTFORWARD, /* OFPRAW_OFPT14_REQUESTFORWARD. */
|
OFPTYPE_REQUESTFORWARD, /* OFPRAW_OFPT14_REQUESTFORWARD. */
|
||||||
|
|
||||||
|
/* Asynchronous messages. */
|
||||||
|
OFPTYPE_TABLE_STATUS, /* OFPRAW_OFPT14_TABLE_STATUS. */
|
||||||
|
|
||||||
OFPTYPE_BUNDLE_CONTROL, /* OFPRAW_OFPT14_BUNDLE_CONTROL. */
|
OFPTYPE_BUNDLE_CONTROL, /* OFPRAW_OFPT14_BUNDLE_CONTROL. */
|
||||||
|
|
||||||
OFPTYPE_BUNDLE_ADD_MESSAGE, /* OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE. */
|
OFPTYPE_BUNDLE_ADD_MESSAGE, /* OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE. */
|
||||||
|
@ -1139,6 +1139,28 @@ ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td)
|
|||||||
ds_put_char(string, '\n');
|
ds_put_char(string, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh)
|
||||||
|
{
|
||||||
|
struct ofputil_table_status ts;
|
||||||
|
enum ofperr error;
|
||||||
|
|
||||||
|
error = ofputil_decode_table_status(oh, &ts);
|
||||||
|
if (error) {
|
||||||
|
ofp_print_error(string, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts.reason == OFPTR_VACANCY_DOWN) {
|
||||||
|
ds_put_format(string, " reason=VACANCY_DOWN");
|
||||||
|
} else if (ts.reason == OFPTR_VACANCY_UP) {
|
||||||
|
ds_put_format(string, " reason=VACANCY_UP");
|
||||||
|
}
|
||||||
|
|
||||||
|
ds_put_format(string, "\ntable_desc:-");
|
||||||
|
ofp_print_table_desc(string, &ts.desc);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ofp_print_queue_get_config_request(struct ds *string,
|
ofp_print_queue_get_config_request(struct ds *string,
|
||||||
const struct ofp_header *oh)
|
const struct ofp_header *oh)
|
||||||
@ -3234,6 +3256,10 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
|
|||||||
ofp_print_requestforward(string, oh);
|
ofp_print_requestforward(string, oh);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OFPTYPE_TABLE_STATUS:
|
||||||
|
ofp_print_table_status_message(string, oh);
|
||||||
|
break;
|
||||||
|
|
||||||
case OFPTYPE_METER_STATS_REQUEST:
|
case OFPTYPE_METER_STATS_REQUEST:
|
||||||
case OFPTYPE_METER_CONFIG_STATS_REQUEST:
|
case OFPTYPE_METER_CONFIG_STATS_REQUEST:
|
||||||
ofp_print_stats(string, oh);
|
ofp_print_stats(string, oh);
|
||||||
|
@ -9645,6 +9645,7 @@ ofputil_is_bundlable(enum ofptype type)
|
|||||||
case OFPTYPE_TABLE_DESC_REPLY:
|
case OFPTYPE_TABLE_DESC_REPLY:
|
||||||
case OFPTYPE_ROLE_STATUS:
|
case OFPTYPE_ROLE_STATUS:
|
||||||
case OFPTYPE_REQUESTFORWARD:
|
case OFPTYPE_REQUESTFORWARD:
|
||||||
|
case OFPTYPE_TABLE_STATUS:
|
||||||
case OFPTYPE_NXT_TLV_TABLE_REQUEST:
|
case OFPTYPE_NXT_TLV_TABLE_REQUEST:
|
||||||
case OFPTYPE_NXT_TLV_TABLE_REPLY:
|
case OFPTYPE_NXT_TLV_TABLE_REPLY:
|
||||||
case OFPTYPE_NXT_RESUME:
|
case OFPTYPE_NXT_RESUME:
|
||||||
@ -10207,3 +10208,89 @@ ofputil_async_cfg_default(enum ofp_version version)
|
|||||||
.slave[OAM_PORT_STATUS] = OFPPR_BITS,
|
.slave[OAM_PORT_STATUS] = OFPPR_BITS,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ofputil_put_ofp14_table_desc(const struct ofputil_table_desc *td,
|
||||||
|
struct ofpbuf *b, enum ofp_version version)
|
||||||
|
{
|
||||||
|
struct ofp14_table_desc *otd;
|
||||||
|
struct ofp14_table_mod_prop_vacancy *otv;
|
||||||
|
size_t start_otd;
|
||||||
|
|
||||||
|
start_otd = b->size;
|
||||||
|
ofpbuf_put_zeros(b, sizeof *otd);
|
||||||
|
|
||||||
|
ofpprop_put_u32(b, OFPTMPT14_EVICTION, td->eviction_flags);
|
||||||
|
|
||||||
|
otv = ofpbuf_put_zeros(b, sizeof *otv);
|
||||||
|
otv->type = htons(OFPTMPT14_VACANCY);
|
||||||
|
otv->length = htons(sizeof *otv);
|
||||||
|
otv->vacancy_down = td->table_vacancy.vacancy_down;
|
||||||
|
otv->vacancy_up = td->table_vacancy.vacancy_up;
|
||||||
|
otv->vacancy = td->table_vacancy.vacancy;
|
||||||
|
|
||||||
|
otd = ofpbuf_at_assert(b, start_otd, sizeof *otd);
|
||||||
|
otd->length = htons(b->size - start_otd);
|
||||||
|
otd->table_id = td->table_id;
|
||||||
|
otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
|
||||||
|
td->eviction, td->vacancy,
|
||||||
|
version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts the abstract form of a "table status" message in '*ts' into an
|
||||||
|
* OpenFlow message suitable for 'protocol', and returns that encoded form in
|
||||||
|
* a buffer owned by the caller. */
|
||||||
|
struct ofpbuf *
|
||||||
|
ofputil_encode_table_status(const struct ofputil_table_status *ts,
|
||||||
|
enum ofputil_protocol protocol)
|
||||||
|
{
|
||||||
|
enum ofp_version version;
|
||||||
|
struct ofpbuf *b;
|
||||||
|
|
||||||
|
version = ofputil_protocol_to_ofp_version(protocol);
|
||||||
|
if (version >= OFP14_VERSION) {
|
||||||
|
enum ofpraw raw;
|
||||||
|
struct ofp14_table_status *ots;
|
||||||
|
|
||||||
|
raw = OFPRAW_OFPT14_TABLE_STATUS;
|
||||||
|
b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
|
||||||
|
ots = ofpbuf_put_zeros(b, sizeof *ots);
|
||||||
|
ots->reason = ts->reason;
|
||||||
|
ofputil_put_ofp14_table_desc(&ts->desc, b, version);
|
||||||
|
ofpmsg_update_length(b);
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decodes the OpenFlow "table status" message in '*ots' into an abstract form
|
||||||
|
* in '*ts'. Returns 0 if successful, otherwise an OFPERR_* value. */
|
||||||
|
enum ofperr
|
||||||
|
ofputil_decode_table_status(const struct ofp_header *oh,
|
||||||
|
struct ofputil_table_status *ts)
|
||||||
|
{
|
||||||
|
const struct ofp14_table_status *ots;
|
||||||
|
struct ofpbuf b;
|
||||||
|
enum ofperr error;
|
||||||
|
enum ofpraw raw;
|
||||||
|
|
||||||
|
ofpbuf_use_const(&b, oh, ntohs(oh->length));
|
||||||
|
raw = ofpraw_pull_assert(&b);
|
||||||
|
ots = ofpbuf_pull(&b, sizeof *ots);
|
||||||
|
|
||||||
|
if (raw == OFPRAW_OFPT14_TABLE_STATUS) {
|
||||||
|
if (ots->reason != OFPTR_VACANCY_DOWN
|
||||||
|
&& ots->reason != OFPTR_VACANCY_UP) {
|
||||||
|
return OFPERR_OFPBPC_BAD_VALUE;
|
||||||
|
}
|
||||||
|
ts->reason = ots->reason;
|
||||||
|
|
||||||
|
error = ofputil_decode_table_desc(&b, &ts->desc, oh->version);
|
||||||
|
return error;
|
||||||
|
} else {
|
||||||
|
return OFPERR_OFPBRC_BAD_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1405,4 +1405,16 @@ enum ofperr ofputil_decode_requestforward(const struct ofp_header *,
|
|||||||
struct ofputil_requestforward *);
|
struct ofputil_requestforward *);
|
||||||
void ofputil_destroy_requestforward(struct ofputil_requestforward *);
|
void ofputil_destroy_requestforward(struct ofputil_requestforward *);
|
||||||
|
|
||||||
|
/* Abstract ofp14_table_status. */
|
||||||
|
struct ofputil_table_status {
|
||||||
|
enum ofp14_table_reason reason; /* One of OFPTR_*. */
|
||||||
|
struct ofputil_table_desc desc; /* New table config. */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ofperr ofputil_decode_table_status(const struct ofp_header *oh,
|
||||||
|
struct ofputil_table_status *ts);
|
||||||
|
|
||||||
|
struct ofpbuf *
|
||||||
|
ofputil_encode_table_status(const struct ofputil_table_status *ts,
|
||||||
|
enum ofputil_protocol protocol);
|
||||||
#endif /* ofp-util.h */
|
#endif /* ofp-util.h */
|
||||||
|
@ -1404,6 +1404,7 @@ is_admitted_msg(const struct ofpbuf *b)
|
|||||||
case OFPTYPE_ROLE_REPLY:
|
case OFPTYPE_ROLE_REPLY:
|
||||||
case OFPTYPE_ROLE_STATUS:
|
case OFPTYPE_ROLE_STATUS:
|
||||||
case OFPTYPE_REQUESTFORWARD:
|
case OFPTYPE_REQUESTFORWARD:
|
||||||
|
case OFPTYPE_TABLE_STATUS:
|
||||||
case OFPTYPE_SET_FLOW_FORMAT:
|
case OFPTYPE_SET_FLOW_FORMAT:
|
||||||
case OFPTYPE_FLOW_MOD_TABLE_ID:
|
case OFPTYPE_FLOW_MOD_TABLE_ID:
|
||||||
case OFPTYPE_SET_PACKET_IN_FORMAT:
|
case OFPTYPE_SET_PACKET_IN_FORMAT:
|
||||||
|
@ -1648,6 +1648,37 @@ connmgr_send_flow_removed(struct connmgr *mgr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sends an OFPT_TABLE_STATUS message with 'reason' to appropriate controllers
|
||||||
|
* managed by 'mgr'. When the table state changes, the controller needs to be
|
||||||
|
* informed with the OFPT_TABLE_STATUS message. The reason values
|
||||||
|
* OFPTR_VACANCY_DOWN and OFPTR_VACANCY_UP identify a vacancy message. The
|
||||||
|
* vacancy events are generated when the remaining space in the flow table
|
||||||
|
* changes and crosses one of the vacancy thereshold specified by
|
||||||
|
* OFPT_TABLE_MOD. */
|
||||||
|
void
|
||||||
|
connmgr_send_table_status(struct connmgr *mgr,
|
||||||
|
const struct ofputil_table_desc *td,
|
||||||
|
uint8_t reason)
|
||||||
|
{
|
||||||
|
struct ofputil_table_status ts;
|
||||||
|
struct ofconn *ofconn;
|
||||||
|
|
||||||
|
ts.reason = reason;
|
||||||
|
ts.desc = *td;
|
||||||
|
|
||||||
|
LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
|
||||||
|
if (ofconn_receives_async_msg(ofconn, OAM_TABLE_STATUS, reason)) {
|
||||||
|
struct ofpbuf *msg;
|
||||||
|
|
||||||
|
msg = ofputil_encode_table_status(&ts,
|
||||||
|
ofconn_get_protocol(ofconn));
|
||||||
|
if (msg) {
|
||||||
|
ofconn_send(ofconn, msg, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as
|
/* Given 'pin', sends an OFPT_PACKET_IN message to each OpenFlow controller as
|
||||||
* necessary according to their individual configurations. */
|
* necessary according to their individual configurations. */
|
||||||
void
|
void
|
||||||
|
@ -217,4 +217,7 @@ void ofmonitor_compose_refresh_updates(struct rule_collection *rules,
|
|||||||
struct ovs_list *msgs)
|
struct ovs_list *msgs)
|
||||||
OVS_REQUIRES(ofproto_mutex);
|
OVS_REQUIRES(ofproto_mutex);
|
||||||
|
|
||||||
|
void connmgr_send_table_status(struct connmgr *,
|
||||||
|
const struct ofputil_table_desc *td,
|
||||||
|
uint8_t reason);
|
||||||
#endif /* connmgr.h */
|
#endif /* connmgr.h */
|
||||||
|
@ -256,8 +256,11 @@ struct oftable {
|
|||||||
#define EVICTION_OPENFLOW (1 << 1) /* Set to 1 if OpenFlow enables eviction. */
|
#define EVICTION_OPENFLOW (1 << 1) /* Set to 1 if OpenFlow enables eviction. */
|
||||||
unsigned int eviction;
|
unsigned int eviction;
|
||||||
|
|
||||||
/* If true, vacancy events are enabled; otherwise they are disabled. */
|
/* If zero, vacancy events are disabled. If nonzero, this is the type of
|
||||||
bool vacancy_enabled;
|
vacancy event that is enabled: either OFPTR_VACANCY_DOWN or
|
||||||
|
OFPTR_VACANCY_UP. Only one type of vacancy event can be enabled at a
|
||||||
|
time. */
|
||||||
|
enum ofp14_table_reason vacancy_event;
|
||||||
|
|
||||||
/* Non-zero values for vacancy_up and vacancy_down indicates that vacancy
|
/* Non-zero values for vacancy_up and vacancy_down indicates that vacancy
|
||||||
* is enabled by table-mod, else these values are set to zero when
|
* is enabled by table-mod, else these values are set to zero when
|
||||||
|
@ -3594,24 +3594,35 @@ handle_table_features_request(struct ofconn *ofconn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns the vacancy of 'oftable', a number that ranges from 0 (if the table
|
||||||
|
* is full) to 100 (if the table is empty).
|
||||||
|
*
|
||||||
|
* A table without a limit on flows is considered to be empty. */
|
||||||
|
static uint8_t
|
||||||
|
oftable_vacancy(const struct oftable *t)
|
||||||
|
{
|
||||||
|
return (!t->max_flows ? 100
|
||||||
|
: t->n_flows >= t->max_flows ? 0
|
||||||
|
: (t->max_flows - t->n_flows) * 100.0 / t->max_flows);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
query_table_desc__(struct ofputil_table_desc *td,
|
query_table_desc__(struct ofputil_table_desc *td,
|
||||||
struct ofproto *ofproto, uint8_t table_id)
|
struct ofproto *ofproto, uint8_t table_id)
|
||||||
{
|
{
|
||||||
unsigned int count = ofproto->tables[table_id].n_flows;
|
const struct oftable *t = &ofproto->tables[table_id];
|
||||||
unsigned int max_flows = ofproto->tables[table_id].max_flows;
|
|
||||||
|
|
||||||
td->table_id = table_id;
|
td->table_id = table_id;
|
||||||
td->eviction = (ofproto->tables[table_id].eviction & EVICTION_OPENFLOW
|
td->eviction = (t->eviction & EVICTION_OPENFLOW
|
||||||
? OFPUTIL_TABLE_EVICTION_ON
|
? OFPUTIL_TABLE_EVICTION_ON
|
||||||
: OFPUTIL_TABLE_EVICTION_OFF);
|
: OFPUTIL_TABLE_EVICTION_OFF);
|
||||||
td->eviction_flags = OFPROTO_EVICTION_FLAGS;
|
td->eviction_flags = OFPROTO_EVICTION_FLAGS;
|
||||||
td->vacancy = (ofproto->tables[table_id].vacancy_enabled
|
td->vacancy = (t->vacancy_event
|
||||||
? OFPUTIL_TABLE_VACANCY_ON
|
? OFPUTIL_TABLE_VACANCY_ON
|
||||||
: OFPUTIL_TABLE_VACANCY_OFF);
|
: OFPUTIL_TABLE_VACANCY_OFF);
|
||||||
td->table_vacancy.vacancy_down = ofproto->tables[table_id].vacancy_down;
|
td->table_vacancy.vacancy_down = t->vacancy_down;
|
||||||
td->table_vacancy.vacancy_up = ofproto->tables[table_id].vacancy_up;
|
td->table_vacancy.vacancy_up = t->vacancy_up;
|
||||||
td->table_vacancy.vacancy = max_flows ? (count * 100) / max_flows : 0;
|
td->table_vacancy.vacancy = oftable_vacancy(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function queries the database for dumping table-desc. */
|
/* This function queries the database for dumping table-desc. */
|
||||||
@ -3651,6 +3662,40 @@ handle_table_desc_request(struct ofconn *ofconn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function determines and sends the vacancy event, based on the value
|
||||||
|
* of current vacancy and threshold vacancy. If the current vacancy is less
|
||||||
|
* than or equal to vacancy_down, vacancy up events must be enabled, and when
|
||||||
|
* the current vacancy is greater or equal to vacancy_up, vacancy down events
|
||||||
|
* must be enabled. */
|
||||||
|
static void
|
||||||
|
send_table_status(struct ofproto *ofproto, uint8_t table_id)
|
||||||
|
{
|
||||||
|
struct oftable *t = &ofproto->tables[table_id];
|
||||||
|
if (!t->vacancy_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t vacancy = oftable_vacancy(t);
|
||||||
|
enum ofp14_table_reason event;
|
||||||
|
if (vacancy < t->vacancy_down) {
|
||||||
|
event = OFPTR_VACANCY_DOWN;
|
||||||
|
} else if (vacancy > t->vacancy_up) {
|
||||||
|
event = OFPTR_VACANCY_UP;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == t->vacancy_event) {
|
||||||
|
struct ofputil_table_desc td;
|
||||||
|
query_table_desc__(&td, ofproto, table_id);
|
||||||
|
connmgr_send_table_status(ofproto->connmgr, &td, event);
|
||||||
|
|
||||||
|
t->vacancy_event = (event == OFPTR_VACANCY_DOWN
|
||||||
|
? OFPTR_VACANCY_UP
|
||||||
|
: OFPTR_VACANCY_DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_port_stat(struct ofport *port, struct ovs_list *replies)
|
append_port_stat(struct ofport *port, struct ovs_list *replies)
|
||||||
{
|
{
|
||||||
@ -4686,6 +4731,9 @@ add_flow_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
|
|||||||
ofmonitor_report(ofproto->connmgr, new_rule, NXFME_ADDED, 0,
|
ofmonitor_report(ofproto->connmgr, new_rule, NXFME_ADDED, 0,
|
||||||
req ? req->ofconn : NULL,
|
req ? req->ofconn : NULL,
|
||||||
req ? req->request->xid : 0, NULL);
|
req ? req->request->xid : 0, NULL);
|
||||||
|
|
||||||
|
/* Send Vacancy Events for OF1.4+. */
|
||||||
|
send_table_status(ofproto, new_rule->table_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
send_buffered_packet(req, fm->buffer_id, new_rule);
|
send_buffered_packet(req, fm->buffer_id, new_rule);
|
||||||
@ -5081,6 +5129,10 @@ delete_flows_finish__(struct ofproto *ofproto,
|
|||||||
ofmonitor_report(ofproto->connmgr, rule, NXFME_DELETED, reason,
|
ofmonitor_report(ofproto->connmgr, rule, NXFME_DELETED, reason,
|
||||||
req ? req->ofconn : NULL,
|
req ? req->ofconn : NULL,
|
||||||
req ? req->request->xid : 0, NULL);
|
req ? req->request->xid : 0, NULL);
|
||||||
|
|
||||||
|
/* Send Vacancy Event for OF1.4+. */
|
||||||
|
send_table_status(ofproto, rule->table_id);
|
||||||
|
|
||||||
ofproto_rule_remove__(ofproto, rule);
|
ofproto_rule_remove__(ofproto, rule);
|
||||||
learned_cookies_dec(ofproto, rule_get_actions(rule),
|
learned_cookies_dec(ofproto, rule_get_actions(rule),
|
||||||
&dead_cookies);
|
&dead_cookies);
|
||||||
@ -6740,11 +6792,16 @@ table_mod__(struct oftable *oftable,
|
|||||||
|
|
||||||
if (tm->vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
|
if (tm->vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
|
||||||
ovs_mutex_lock(&ofproto_mutex);
|
ovs_mutex_lock(&ofproto_mutex);
|
||||||
oftable->vacancy_enabled = (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON
|
|
||||||
? OFPTC14_VACANCY_EVENTS
|
|
||||||
: 0);
|
|
||||||
oftable->vacancy_down = tm->table_vacancy.vacancy_down;
|
oftable->vacancy_down = tm->table_vacancy.vacancy_down;
|
||||||
oftable->vacancy_up = tm->table_vacancy.vacancy_up;
|
oftable->vacancy_up = tm->table_vacancy.vacancy_up;
|
||||||
|
if (tm->vacancy == OFPUTIL_TABLE_VACANCY_OFF) {
|
||||||
|
oftable->vacancy_event = 0;
|
||||||
|
} else if (!oftable->vacancy_event) {
|
||||||
|
uint8_t vacancy = oftable_vacancy(oftable);
|
||||||
|
oftable->vacancy_event = (vacancy < oftable->vacancy_up
|
||||||
|
? OFPTR_VACANCY_UP
|
||||||
|
: OFPTR_VACANCY_DOWN);
|
||||||
|
}
|
||||||
ovs_mutex_unlock(&ofproto_mutex);
|
ovs_mutex_unlock(&ofproto_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7328,6 +7385,7 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
|
|||||||
case OFPTYPE_TABLE_DESC_REPLY:
|
case OFPTYPE_TABLE_DESC_REPLY:
|
||||||
case OFPTYPE_ROLE_STATUS:
|
case OFPTYPE_ROLE_STATUS:
|
||||||
case OFPTYPE_REQUESTFORWARD:
|
case OFPTYPE_REQUESTFORWARD:
|
||||||
|
case OFPTYPE_TABLE_STATUS:
|
||||||
case OFPTYPE_NXT_TLV_TABLE_REPLY:
|
case OFPTYPE_NXT_TLV_TABLE_REPLY:
|
||||||
default:
|
default:
|
||||||
if (ofpmsg_is_stat_request(oh)) {
|
if (ofpmsg_is_stat_request(oh)) {
|
||||||
|
@ -1999,7 +1999,7 @@ AT_CHECK([ovs-ofctl -O OpenFlow14 dump-table-desc br0 | sed '/^$/d
|
|||||||
AT_CHECK([ovs-ofctl -O Openflow14 mod-table br0 0 vacancy:20,80])
|
AT_CHECK([ovs-ofctl -O Openflow14 mod-table br0 0 vacancy:20,80])
|
||||||
# Check that the configuration was updated.
|
# Check that the configuration was updated.
|
||||||
mv expout orig-expout
|
mv expout orig-expout
|
||||||
sed -e '3s/vacancy=off/vacancy=on vacancy_down=20% vacancy_up=80% vacancy=0%/' <orig-expout > expout
|
sed -e '3s/vacancy=off/vacancy=on vacancy_down=20% vacancy_up=80% vacancy=100%/' <orig-expout > expout
|
||||||
AT_CHECK([ovs-ofctl -O OpenFlow14 dump-table-desc br0 | sed '/^$/d
|
AT_CHECK([ovs-ofctl -O OpenFlow14 dump-table-desc br0 | sed '/^$/d
|
||||||
/^OFPST_TABLE_DESC/d'], [0], [expout])
|
/^OFPST_TABLE_DESC/d'], [0], [expout])
|
||||||
OVS_VSWITCHD_STOP
|
OVS_VSWITCHD_STOP
|
||||||
@ -2907,7 +2907,7 @@ OFPT_PORT_STATUS (OF1.4): MOD: ${INDEX}(test): addr:aa:55:aa:55:00:0x
|
|||||||
echo >>expout "OFPT_FLOW_REMOVED (OF1.4): reason=delete table_id=0"
|
echo >>expout "OFPT_FLOW_REMOVED (OF1.4): reason=delete table_id=0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# OFPT_FLOW_REMOVED, OFPRR_GROUP_DELETE
|
# OFPT_FLOW_REMOVED, OFPRR_GROUP_DELETE
|
||||||
ovs-ofctl -O OpenFlow14 add-group br0 group_id=1234,type=all,bucket=output:10
|
ovs-ofctl -O OpenFlow14 add-group br0 group_id=1234,type=all,bucket=output:10
|
||||||
ovs-ofctl -O OpenFlow14 add-flow br0 send_flow_rem,actions=group:1234
|
ovs-ofctl -O OpenFlow14 add-flow br0 send_flow_rem,actions=group:1234
|
||||||
ovs-ofctl -O OpenFlow14 --strict del-groups br0 group_id=1234
|
ovs-ofctl -O OpenFlow14 --strict del-groups br0 group_id=1234
|
||||||
@ -2915,6 +2915,84 @@ OFPT_PORT_STATUS (OF1.4): MOD: ${INDEX}(test): addr:aa:55:aa:55:00:0x
|
|||||||
echo >>expout "OFPT_FLOW_REMOVED (OF1.4): reason=group_delete table_id=0"
|
echo >>expout "OFPT_FLOW_REMOVED (OF1.4): reason=group_delete table_id=0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# OFPT_TABLE_STATUS, OFPTR_VACANCY_UP
|
||||||
|
if test X"$1" = X"OFPTR_VACANCY_UP"; then shift;
|
||||||
|
ovs-vsctl -- --id=@t1 create Flow_Table flow-limit=10 -- set bridge br0 flow_tables:1=@t1
|
||||||
|
|
||||||
|
# Turn on vacancy events, then add flows until we're full.
|
||||||
|
# With initial vacancy of 100% and vacancy_up of 80%, so that
|
||||||
|
# vacancy >= vacancy_up, this enables VACANY_DOWN events, so
|
||||||
|
# we get a single such message when vacancy dips below 20%.
|
||||||
|
ovs-ofctl -O OpenFlow14 mod-table br0 1 vacancy:20,80
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=1,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=2,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=3,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=4,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=5,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=6,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=7,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=8,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=9,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=10,actions=2
|
||||||
|
echo >>expout "OFPT_TABLE_STATUS (OF1.4): reason=VACANCY_DOWN
|
||||||
|
table_desc:-
|
||||||
|
table 1:
|
||||||
|
eviction=off eviction_flags=OTHER|IMPORTANCE|LIFETIME
|
||||||
|
vacancy=on vacancy_down=20% vacancy_up=80% vacancy=10%"
|
||||||
|
# Then delete flows until we're empty. Sending the
|
||||||
|
# VACANCY_DOWN message enabled VACANCY_UP events, so we get a
|
||||||
|
# single such message when vacancy rises above 80%.
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=1
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=2
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=3
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=4
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=5
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=6
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=7
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=8
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=9
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=10
|
||||||
|
echo >>expout "OFPT_TABLE_STATUS (OF1.4): reason=VACANCY_UP
|
||||||
|
table_desc:-
|
||||||
|
table 1:
|
||||||
|
eviction=off eviction_flags=OTHER|IMPORTANCE|LIFETIME
|
||||||
|
vacancy=on vacancy_down=20% vacancy_up=80% vacancy=90%"
|
||||||
|
|
||||||
|
# Now approach vacancy from the other direction. First
|
||||||
|
# disable vacancy events. With initial vacancy of 70%, so
|
||||||
|
# that vacancy < vacancy_up, this enables VACANCY_UP events.
|
||||||
|
# That means that filling up the table generates no message,
|
||||||
|
# but deleting all the flows generates VACANCY_UP at the point
|
||||||
|
# vacancy rises above 80%.
|
||||||
|
ovs-ofctl -O OpenFlow14 mod-table br0 1 novacancy
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=1,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=2,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=3,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 mod-table br0 1 vacancy:20,80
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=4,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=5,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=6,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=7,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=8,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=9,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 add-flow br0 table=1,in_port=10,actions=2
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=1
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=2
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=3
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=4
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=5
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=6
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=7
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=8
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=9
|
||||||
|
ovs-ofctl -O OpenFlow14 del-flows br0 table=1,in_port=10
|
||||||
|
echo >>expout "OFPT_TABLE_STATUS (OF1.4): reason=VACANCY_UP
|
||||||
|
table_desc:-
|
||||||
|
table 1:
|
||||||
|
eviction=off eviction_flags=OTHER|IMPORTANCE|LIFETIME
|
||||||
|
vacancy=on vacancy_down=20% vacancy_up=80% vacancy=90%"
|
||||||
|
fi
|
||||||
|
|
||||||
AT_FAIL_IF([test X"$1" != X])
|
AT_FAIL_IF([test X"$1" != X])
|
||||||
|
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
@ -2940,8 +3018,8 @@ ovs-appctl -t ovs-ofctl ofctl/send 051800180000000200000003000000000000000000000
|
|||||||
check_async 3 OFPPR_ADD OFPPR_MODIFY OFPPR_DELETE
|
check_async 3 OFPPR_ADD OFPPR_MODIFY OFPPR_DELETE
|
||||||
|
|
||||||
# Use OF 1.4 OFPT_SET_ASYNC to enable a patchwork of asynchronous messages.
|
# Use OF 1.4 OFPT_SET_ASYNC to enable a patchwork of asynchronous messages.
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send 051c0038000000020000000800000005000100080000000200020008000000020003000800000005000400080000001c0005000800000005
|
ovs-appctl -t ovs-ofctl ofctl/send 051c0040000000020000000800000005000100080000000200020008000000020003000800000005000400080000001c00050008000000050008000800000018
|
||||||
check_async 4 OFPR_INVALID_TTL OFPPR_DELETE OFPRR_DELETE OFPRR_GROUP_DELETE
|
check_async 4 OFPR_INVALID_TTL OFPPR_DELETE OFPRR_DELETE OFPRR_GROUP_DELETE OFPTR_VACANCY_UP
|
||||||
|
|
||||||
# Set controller ID 123.
|
# Set controller ID 123.
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send 05040018000000030000232000000014000000000000007b
|
ovs-appctl -t ovs-ofctl ofctl/send 05040018000000030000232000000014000000000000007b
|
||||||
|
Loading…
x
Reference in New Issue
Block a user