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
ofproto_flush_flows__(p);
HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) {
- hmap_remove(&p->ports, &ofport->hmap_node);
ofport_destroy(ofport);
}
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);
- ots[i].wildcards = htonl(OVSFW_ALL);
+ 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]));
}
p->ofproto_class->get_tables(p, ots);
- if (ofconn_get_flow_format(ofconn) == NXFF_OPENFLOW10) {
- /* OpenFlow 1.0 only supports the OFPFW_* bits. */
- for (i = 0; i < p->n_tables; i++) {
- ots[i].wildcards &= htonl(OFPFW_ALL);
- }
- }
-
ofconn_send_reply(ofconn, msg);
return 0;
}
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
struct ofp_flow_stats *ofs;
uint64_t packet_count, byte_count;
- ovs_be64 cookie;
size_t act_len, len;
if (rule_is_hidden(rule) || !rule_has_out_port(rule, out_port)) {
ofs->length = htons(len);
ofs->table_id = rule->table_id;
ofs->pad = 0;
- ofputil_cls_rule_to_match(&rule->cr, ofconn_get_flow_format(ofconn),
- &ofs->match, rule->flow_cookie, &cookie);
- put_32aligned_be64(&ofs->cookie, cookie);
+ ofputil_cls_rule_to_match(&rule->cr, &ofs->match);
+ put_32aligned_be64(&ofs->cookie, rule->flow_cookie);
calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
ofs->priority = htons(rule->cr.priority);
ofs->idle_timeout = htons(rule->idle_timeout);
COVERAGE_INC(ofproto_flows_req);
reply = start_ofp_stats_reply(oh, 1024);
- ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target);
+ ofputil_cls_rule_from_match(&fsr->match, 0, &target);
FOR_EACH_MATCHING_TABLE (cls, fsr->table_id, ofproto) {
struct cls_cursor cursor;
struct rule *rule;
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,
struct cls_rule target;
struct ofpbuf *msg;
- ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0,
- &target);
+ ofputil_cls_rule_from_match(&request->match, 0, &target);
msg = start_ofp_stats_reply(oh, sizeof *reply);
reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
}
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) {
return error;
}
- error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_flow_format(ofconn),
+ error = ofputil_decode_flow_mod(&fm, oh,
ofconn_get_flow_mod_table_id(ofconn));
if (error) {
return error;
}
}
-static int
-handle_tun_id_from_cookie(struct ofconn *ofconn, const struct ofp_header *oh)
-{
- const struct nxt_tun_id_cookie *msg
- = (const struct nxt_tun_id_cookie *) oh;
- enum nx_flow_format flow_format;
-
- flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10;
- ofconn_set_flow_format(ofconn, flow_format);
-
- return 0;
-}
-
static int
handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
format = ntohl(msg->format);
if (format == NXFF_OPENFLOW10
- || format == NXFF_TUN_ID_FROM_COOKIE
|| format == NXFF_NXM) {
ofconn_set_flow_format(ofconn, format);
return 0;
return 0;
/* Nicira extension requests. */
- case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
- return handle_tun_id_from_cookie(ofconn, oh);
-
case OFPUTIL_NXT_ROLE_REQUEST:
return handle_role_request(ofconn, oh);