static void ofport_destroy__(struct ofport *);
static void ofport_destroy(struct ofport *);
-static int rule_create(struct ofproto *, const struct cls_rule *,
+static int rule_create(struct ofproto *,
+ const struct cls_rule *, uint8_t table_id,
const union ofp_action *, size_t n_actions,
uint16_t idle_timeout, uint16_t hard_timeout,
ovs_be64 flow_cookie, bool send_flow_removed,
{
struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
if (ofport && ofproto->ofproto_class->set_cfm) {
- ofproto->ofproto_class->set_cfm(ofport, NULL, NULL, 0);
+ ofproto->ofproto_class->set_cfm(ofport, NULL);
}
}
/* Configures connectivity fault management on 'ofp_port' in 'ofproto'. Takes
- * basic configuration from the configuration members in 'cfm', and the set of
- * remote maintenance points from the 'n_remote_mps' elements in 'remote_mps'.
- * Ignores the statistics members of 'cfm'.
+ * basic configuration from the configuration members in 'cfm', and the remote
+ * maintenance point ID from remote_mpid. Ignores the statistics members of
+ * 'cfm'.
*
* This function has no effect if 'ofproto' does not have a port 'ofp_port'. */
void
ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port,
- const struct cfm *cfm,
- const uint16_t *remote_mps, size_t n_remote_mps)
+ const struct cfm_settings *s)
{
struct ofport *ofport;
int error;
return;
}
+ /* XXX: For configuration simplicity, we only support one remote_mpid
+ * outside of the CFM module. It's not clear if this is the correct long
+ * term solution or not. */
error = (ofproto->ofproto_class->set_cfm
- ? ofproto->ofproto_class->set_cfm(ofport, cfm,
- remote_mps, n_remote_mps)
+ ? ofproto->ofproto_class->set_cfm(ofport, s)
: EOPNOTSUPP);
if (error) {
VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)",
}
}
-/* Returns the connectivity fault management object associated with 'ofp_port'
- * within 'ofproto', or a null pointer if 'ofproto' does not have a port
- * 'ofp_port' or if that port does not have CFM configured. The caller must
- * not modify or destroy the returned object. */
-const struct cfm *
-ofproto_port_get_cfm(struct ofproto *ofproto, uint16_t ofp_port)
-{
- struct ofport *ofport;
- const struct cfm *cfm;
-
- ofport = ofproto_get_port(ofproto, ofp_port);
- return (ofport
- && ofproto->ofproto_class->get_cfm
- && !ofproto->ofproto_class->get_cfm(ofport, &cfm)) ? cfm : NULL;
-}
-
/* Checks the status of LACP negotiation for 'ofp_port' within ofproto.
* Returns 1 if LACP partner information for 'ofp_port' is up-to-date,
* 0 if LACP partner information is not current (generally indicating a
const union ofp_action *actions, size_t n_actions)
{
struct rule *rule;
- rule_create(p, cls_rule, actions, n_actions, 0, 0, 0, false, &rule);
+ rule_create(p, cls_rule, 0, actions, n_actions, 0, 0, 0, false, &rule);
}
/* Searches for a rule with matching criteria exactly equal to 'target' in
struct ofport *port = ofproto_get_port(ofproto, ofp_port);
if (port) {
if (port->ofproto->ofproto_class->set_cfm) {
- port->ofproto->ofproto_class->set_cfm(port, NULL, NULL, 0);
+ port->ofproto->ofproto_class->set_cfm(port, NULL);
}
if (port->ofproto->ofproto_class->bundle_remove) {
port->ofproto->ofproto_class->bundle_remove(port);
if (netdev) {
port = ofproto_get_port(ofproto, ofproto_port.ofp_port);
if (port && !strcmp(netdev_get_name(port->netdev), name)) {
+ struct netdev *old_netdev = port->netdev;
+
/* 'name' hasn't changed location. Any properties changed? */
if (!ofport_equal(&port->opp, &opp)) {
ofport_modified(port, &opp);
}
- /* Install the newly opened netdev in case it has changed. */
+ /* Install the newly opened netdev in case it has changed.
+ * Don't close the old netdev yet in case port_modified has to
+ * remove a retained reference to it.*/
netdev_monitor_remove(ofproto->netdev_monitor, port->netdev);
netdev_monitor_add(ofproto->netdev_monitor, netdev);
-
- netdev_close(port->netdev);
port->netdev = netdev;
if (port->ofproto->ofproto_class->port_modified) {
port->ofproto->ofproto_class->port_modified(port);
}
+
+ netdev_close(old_netdev);
} else {
/* If 'port' is nonnull then its name differs from 'name' and thus
* we should delete it. If we think there's a port named 'name'
* flow table, and stores the new rule into '*rulep'. Returns 0 on success,
* otherwise a positive errno value or OpenFlow error code. */
static int
-rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule,
+rule_create(struct ofproto *ofproto,
+ const struct cls_rule *cls_rule, uint8_t table_id,
const union ofp_action *actions, size_t n_actions,
uint16_t idle_timeout, uint16_t hard_timeout,
ovs_be64 flow_cookie, bool send_flow_removed,
struct rule *rule;
int error;
+ if (table_id == 0xff) {
+ if (ofproto->n_tables > 1) {
+ error = ofproto->ofproto_class->rule_choose_table(ofproto,
+ cls_rule,
+ &table_id);
+ if (error) {
+ return error;
+ }
+ assert(table_id < ofproto->n_tables);
+ } else {
+ table_id = 0;
+ }
+ }
+
rule = ofproto->ofproto_class->rule_alloc();
if (!rule) {
error = ENOMEM;
rule->ofproto = ofproto;
rule->cr = *cls_rule;
+ rule->table_id = table_id;
rule->flow_cookie = flow_cookie;
rule->created = time_msec();
rule->idle_timeout = idle_timeout;
*
* The log message mentions 'msg_type'. */
static int
-reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
+reject_slave_controller(struct ofconn *ofconn, const char *msg_type)
{
if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
&& ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables);
for (i = 0; i < p->n_tables; i++) {
ots[i].table_id = i;
- sprintf(ots[i].name, "table%d", i);
+ sprintf(ots[i].name, "table%zu", i);
ots[i].wildcards = htonl(OFPFW_ALL);
ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */
ots[i].active_count = htonl(classifier_count(&p->tables[i]));
ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, engine_id);
}
+/* Checks the fault status of CFM for 'ofp_port' within 'ofproto'. Returns 1
+ * if CFM is faulted (generally indiciating a connectivity problem), 0 if CFM
+ * is not faulted, and -1 if CFM is not enabled on 'ofp_port'. */
+int
+ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port)
+{
+ struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
+ return (ofport && ofproto->ofproto_class->get_cfm_fault
+ ? ofproto->ofproto_class->get_cfm_fault(ofport)
+ : -1);
+}
+
static void
query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target,
ovs_be16 out_port, uint8_t table_id,
}
buf_err = ofconn_pktbuf_retrieve(ofconn, fm->buffer_id, &packet, &in_port);
- error = rule_create(p, &fm->cr, fm->actions, fm->n_actions,
+ error = rule_create(p, &fm->cr, fm->table_id, fm->actions, fm->n_actions,
fm->idle_timeout, fm->hard_timeout, fm->cookie,
fm->flags & OFPFF_SEND_FLOW_REM, &rule);
if (error) {