@@ -4347,6 +4347,7 @@ const struct dpif_class dpif_netdev_class = {
dpif_netdev_get_stats,
dpif_netdev_port_add,
dpif_netdev_port_del,
+ NULL, /* port_set_config */
dpif_netdev_port_query_by_number,
dpif_netdev_port_query_by_name,
NULL, /* port_get_pid */
@@ -2348,6 +2348,7 @@ const struct dpif_class dpif_netlink_class = {
dpif_netlink_get_stats,
dpif_netlink_port_add,
dpif_netlink_port_del,
+ NULL, /* port_set_config */
dpif_netlink_port_query_by_number,
dpif_netlink_port_query_by_name,
dpif_netlink_port_get_pid,
@@ -167,6 +167,11 @@ struct dpif_class {
/* Removes port numbered 'port_no' from 'dpif'. */
int (*port_del)(struct dpif *dpif, odp_port_t port_no);
+ /* Refreshes configuration of 'dpif's port. The implementation might
+ * postpone applying the changes until run() is called. */
+ int (*port_set_config)(struct dpif *dpif, odp_port_t port_no,
+ const struct smap *cfg);
+
/* Queries 'dpif' for a port with the given 'port_no' or 'devname'.
* If 'port' is not null, stores information about the port into
* '*port' if successful.
@@ -610,6 +610,23 @@ dpif_port_exists(const struct dpif *dpif, const char *devname)
return !error;
}
+/* Refreshes configuration of 'dpif's port. */
+int
+dpif_port_set_config(struct dpif *dpif, odp_port_t port_no,
+ const struct smap *cfg)
+{
+ int error = 0;
+
+ if (dpif->dpif_class->port_set_config) {
+ error = dpif->dpif_class->port_set_config(dpif, port_no, cfg);
+ if (error) {
+ log_operation(dpif, "port_set_config", error);
+ }
+ }
+
+ return error;
+}
+
/* Looks up port number 'port_no' in 'dpif'. On success, returns 0 and
* initializes '*port' appropriately; on failure, returns a positive errno
* value.
@@ -839,6 +839,7 @@ void dpif_register_upcall_cb(struct dpif *, upcall_callback *, void *aux);
int dpif_recv_set(struct dpif *, bool enable);
int dpif_handlers_set(struct dpif *, uint32_t n_handlers);
int dpif_poll_threads_set(struct dpif *, const char *cmask);
+int dpif_port_set_config(struct dpif *, odp_port_t, const struct smap *cfg);
int dpif_recv(struct dpif *, uint32_t handler_id, struct dpif_upcall *,
struct ofpbuf *);
void dpif_recv_purge(struct dpif *);
@@ -3543,6 +3543,20 @@ port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
}
static int
+port_set_config(const struct ofport *ofport_, const struct smap *cfg)
+{
+ struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+
+ if (sset_contains(&ofproto->ghost_ports,
+ netdev_get_name(ofport->up.netdev))) {
+ return 0;
+ }
+
+ return dpif_port_set_config(ofproto->backer->dpif, ofport->odp_port, cfg);
+}
+
+static int
port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
@@ -5610,6 +5624,7 @@ const struct ofproto_class ofproto_dpif_class = {
port_query_by_name,
port_add,
port_del,
+ port_set_config,
port_get_stats,
port_dump_start,
port_dump_next,
@@ -972,6 +972,10 @@ struct ofproto_class {
* convenient. */
int (*port_del)(struct ofproto *ofproto, ofp_port_t ofp_port);
+ /* Refreshes datapath configuration of 'port'.
+ * Returns 0 if successful, otherwise a positive errno value. */
+ int (*port_set_config)(const struct ofport *port, const struct smap *cfg);
+
/* Get port stats */
int (*port_get_stats)(const struct ofport *port,
struct netdev_stats *stats);
@@ -2079,6 +2079,35 @@ ofproto_port_del(struct ofproto *ofproto, ofp_port_t ofp_port)
return error;
}
+/* Refreshes datapath configuration of port number 'ofp_port' in 'ofproto'.
+ *
+ * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */
+void
+ofproto_port_set_config(struct ofproto *ofproto, ofp_port_t ofp_port,
+ const struct smap *cfg)
+{
+ struct ofport *ofport;
+ int error;
+
+ ofport = ofproto_get_port(ofproto, ofp_port);
+ if (!ofport) {
+ VLOG_WARN("%s: cannot configure datapath on nonexistent port %"PRIu16,
+ ofproto->name, ofp_port);
+ return;
+ }
+
+ error = (ofproto->ofproto_class->port_set_config
+ ? ofproto->ofproto_class->port_set_config(ofport, cfg)
+ : EOPNOTSUPP);
+ if (error) {
+ VLOG_WARN("%s: datapath configuration on port %"PRIu16
+ " (%s) failed (%s)",
+ ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
+ ovs_strerror(error));
+ }
+}
+
+
static void
flow_mod_init(struct ofputil_flow_mod *fm,
const struct match *match, int priority,
@@ -293,6 +293,8 @@ const char *ofproto_port_open_type(const char *datapath_type,
const char *port_type);
int ofproto_port_add(struct ofproto *, struct netdev *, ofp_port_t *ofp_portp);
int ofproto_port_del(struct ofproto *, ofp_port_t ofp_port);
+void ofproto_port_set_config(struct ofproto *, ofp_port_t ofp_port,
+ const struct smap *cfg);
int ofproto_port_get_stats(const struct ofport *, struct netdev_stats *stats);
int ofproto_port_query_by_name(const struct ofproto *, const char *devname,
@@ -655,6 +655,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
&iface->cfg->bfd);
ofproto_port_set_lldp(br->ofproto, iface->ofp_port,
&iface->cfg->lldp);
+ ofproto_port_set_config(br->ofproto, iface->ofp_port,
+ &iface->cfg->other_config);
}
}
bridge_configure_mirrors(br);