[ovs-dev] [PATCH v3] Add configurable OpenFlow port name.
Flavio Leitner
fbl at sysclose.org
Mon May 9 20:28:16 UTC 2016
On Sat, Apr 23, 2016 at 01:26:17PM +0800, Xiao Liang wrote:
> Add new column "ofname" in Interface table to configure port name reported
> to controllers with OpenFlow protocol, thus decouple OpenFlow port name from
> device name.
>
> For example:
> # ovs-vsctl set Interface eth0 ofname=wan
> # ovs-vsctl set Interface eth1 ofname=lan0
> then controllers can recognize ports by their names.
This change is nice because now the same setup like a "compute node"
can use the same logical name to refer to a specific interface that
could have different netdev name on different HW.
Comments inline.
> Signed-off-by: Xiao Liang <shaw.leon at gmail.com>
> ---
> v2: Added test for ofname
> Increased db schema version
> Updated NEWS
> v3: Rebase
> ---
> NEWS | 1 +
> lib/db-ctl-base.h | 2 +-
> ofproto/ofproto-provider.h | 1 +
> ofproto/ofproto.c | 67 ++++++++++++++++++++++++++++++++++++++++++++--
> ofproto/ofproto.h | 9 ++++++-
> tests/ofproto.at | 60 +++++++++++++++++++++++++++++++++++++++++
> utilities/ovs-vsctl.c | 1 +
> vswitchd/bridge.c | 10 +++++--
> vswitchd/vswitch.ovsschema | 6 +++--
> vswitchd/vswitch.xml | 14 ++++++++++
> 10 files changed, 163 insertions(+), 8 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index ea7f3a1..156781c 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -15,6 +15,7 @@ Post-v2.5.0
> now implemented. Only flow mod and port mod messages are supported
> in bundles.
> * New OpenFlow extension NXM_NX_MPLS_TTL to provide access to MPLS TTL.
> + * Port name can now be set with "ofname" column in the Interface table.
> - ovs-ofctl:
> * queue-get-config command now allows a queue ID to be specified.
> * '--bundle' option can now be used with OpenFlow 1.3.
> diff --git a/lib/db-ctl-base.h b/lib/db-ctl-base.h
> index f8f576b..5bd62d5 100644
> --- a/lib/db-ctl-base.h
> +++ b/lib/db-ctl-base.h
> @@ -177,7 +177,7 @@ struct weak_ref_table {
> struct cmd_show_table {
> const struct ovsdb_idl_table_class *table;
> const struct ovsdb_idl_column *name_column;
> - const struct ovsdb_idl_column *columns[3]; /* Seems like a good number. */
> + const struct ovsdb_idl_column *columns[4]; /* Seems like a good number. */
> const struct weak_ref_table wref_table;
> };
>
> diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> index daa0077..8795242 100644
> --- a/ofproto/ofproto-provider.h
> +++ b/ofproto/ofproto-provider.h
> @@ -84,6 +84,7 @@ struct ofproto {
> struct hmap ports; /* Contains "struct ofport"s. */
> struct shash port_by_name;
> struct simap ofp_requests; /* OpenFlow port number requests. */
> + struct smap ofp_names; /* OpenFlow port names. */
> uint16_t alloc_port_no; /* Last allocated OpenFlow port number. */
> uint16_t max_ports; /* Max possible OpenFlow port num, plus one. */
> struct hmap ofport_usage; /* Map ofport to last used time. */
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index ff6affd..a2799f4 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -550,6 +550,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
> hmap_init(&ofproto->ofport_usage);
> shash_init(&ofproto->port_by_name);
> simap_init(&ofproto->ofp_requests);
> + smap_init(&ofproto->ofp_names);
> ofproto->max_ports = ofp_to_u16(OFPP_MAX);
> ofproto->eviction_group_timer = LLONG_MIN;
> ofproto->tables = NULL;
> @@ -1546,6 +1547,7 @@ ofproto_destroy__(struct ofproto *ofproto)
> hmap_destroy(&ofproto->ofport_usage);
> shash_destroy(&ofproto->port_by_name);
> simap_destroy(&ofproto->ofp_requests);
> + smap_destroy(&ofproto->ofp_names);
>
> OFPROTO_FOR_EACH_TABLE (table, ofproto) {
> oftable_destroy(table);
> @@ -1945,7 +1947,7 @@ ofproto_port_open_type(const char *datapath_type, const char *port_type)
> * 'ofp_portp' is non-null). */
> int
> ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
> - ofp_port_t *ofp_portp)
> + ofp_port_t *ofp_portp, const char *ofp_name)
> {
> ofp_port_t ofp_port = ofp_portp ? *ofp_portp : OFPP_NONE;
> int error;
> @@ -1956,6 +1958,9 @@ ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
>
> simap_put(&ofproto->ofp_requests, netdev_name,
> ofp_to_u16(ofp_port));
> + if (ofp_name) {
> + smap_replace(&ofproto->ofp_names, netdev_name, ofp_name);
Should it be unique? See below.
> + }
> error = update_port(ofproto, netdev_name);
> }
> if (ofp_portp) {
> @@ -2009,6 +2014,8 @@ ofproto_port_del(struct ofproto *ofproto, ofp_port_t ofp_port)
> simap_delete(&ofproto->ofp_requests, ofp_request_node);
> }
>
> + smap_remove(&ofproto->ofp_names, name);
> +
> error = ofproto->ofproto_class->port_del(ofproto, ofp_port);
> if (!error && ofport) {
> /* 'name' is the netdev's name and update_port() is going to close the
> @@ -2285,6 +2292,7 @@ ofport_open(struct ofproto *ofproto,
> {
> enum netdev_flags flags;
> struct netdev *netdev;
> + const char *ofp_name;
> int error;
>
> error = netdev_open(ofproto_port->name, ofproto_port->type, &netdev);
> @@ -2307,7 +2315,13 @@ ofport_open(struct ofproto *ofproto,
> }
> pp->port_no = ofproto_port->ofp_port;
> netdev_get_etheraddr(netdev, &pp->hw_addr);
> - ovs_strlcpy(pp->name, ofproto_port->name, sizeof pp->name);
> +
> + ofp_name = smap_get(&ofproto->ofp_names, ofproto_port->name);
> + if (!ofp_name) {
> + ofp_name = ofproto_port->name;
> + }
> + ovs_strlcpy(pp->name, ofp_name, sizeof pp->name);
Before pp->name was the device's name which is unique on the system.
Now pp->name can change to some other random string which ovs-ofctl
mod-port will use it. The new name also needs to be unique, right?
> +
> netdev_get_flags(netdev, &flags);
> pp->config = flags & NETDEV_UP ? 0 : OFPUTIL_PC_PORT_DOWN;
> pp->state = netdev_get_carrier(netdev) ? 0 : OFPUTIL_PS_LINK_DOWN;
> @@ -8011,3 +8025,52 @@ ofproto_port_set_realdev(struct ofproto *ofproto, ofp_port_t vlandev_ofp_port,
> }
> return error;
> }
> +
> +const char *
> +ofproto_port_get_ofpname(struct ofproto *ofproto, ofp_port_t ofp_port)
> +{
> + struct ofport *ofport;
> +
> + ofport = ofproto_get_port(ofproto, ofp_port);
> + return (ofport ? ofport->pp.name : NULL);
> +}
> +
> +void
> +ofproto_port_set_ofpname(struct ofproto *ofproto, ofp_port_t ofp_port,
> + const char *ofp_name)
> +{
> + struct ofport *ofport;
> + const char *devname;
> + size_t name_size;
> +
> + ofport = ofproto_get_port(ofproto, ofp_port);
> + if (!ofport) {
> + return;
> + }
> +
> + devname = netdev_get_name(ofport->netdev);
> + name_size = sizeof(ofport->pp.name);
> +
> + if (!devname ||
> + (ofp_name && !strncmp(ofp_name, ofport->pp.name, name_size - 1)) ||
> + (!ofp_name && !strncmp(devname, ofport->pp.name, name_size - 1))) {
> + /* No need to change port name. */
> + return;
> + }
> +
> + /* Send a OFPPR_DELETE followed by OFPPR_ADD port_status message
> + * to notify controller a port name change. */
> + connmgr_send_port_status(ofproto->connmgr, NULL, &ofport->pp,
> + OFPPR_DELETE);
> +
> + if (!ofp_name) {
> + smap_remove(&ofproto->ofp_names, devname);
> + ovs_strlcpy(ofport->pp.name, devname, name_size);
> + } else {
> + smap_replace(&ofproto->ofp_names, netdev_get_name(ofport->netdev),
> + ofp_name);
> + ovs_strlcpy(ofport->pp.name, ofp_name, name_size);
> + }
> + connmgr_send_port_status(ofproto->connmgr, NULL, &ofport->pp,
> + OFPPR_ADD);
> +}
> diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
> index 2d241c9..3382ef1 100644
> --- a/ofproto/ofproto.h
> +++ b/ofproto/ofproto.h
> @@ -288,7 +288,8 @@ int ofproto_port_dump_done(struct ofproto_port_dump *);
>
> 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_add(struct ofproto *, struct netdev *, ofp_port_t *ofp_portp,
> + const char *);
> int ofproto_port_del(struct ofproto *, ofp_port_t ofp_port);
> int ofproto_port_get_stats(const struct ofport *, struct netdev_stats *stats);
>
> @@ -521,6 +522,12 @@ int ofproto_port_set_realdev(struct ofproto *, ofp_port_t vlandev_ofp_port,
> enum ofputil_table_miss ofproto_table_get_miss_config(const struct ofproto *,
> uint8_t table_id);
>
> +const char *ofproto_port_get_ofpname(struct ofproto *ofproto,
> + ofp_port_t ofp_port);
> +void ofproto_port_set_ofpname(struct ofproto *ofproto,
> + ofp_port_t ofp_port,
> + const char *ofp_name);
> +
Looks like those belong to the "Configuration of ports" section.
> #ifdef __cplusplus
> }
> #endif
> diff --git a/tests/ofproto.at b/tests/ofproto.at
> index c4260ab..5f38160 100644
> --- a/tests/ofproto.at
> +++ b/tests/ofproto.at
> @@ -77,6 +77,66 @@ OFPT_GET_CONFIG_REPLY: frags=normal miss_send_len=0
> OVS_VSWITCHD_STOP
> AT_CLEANUP
>
> +AT_SETUP([ofproto - set OpenFlow port name])
> +OVS_VSWITCHD_START(
> + [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 --\
> + add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2 ofname=n2])
> +check_ofname () {
> + AT_CHECK([ovs-ofctl -vwarn show br0], [0], [stdout])
> + echo >expout "OFPT_FEATURES_REPLY: dpid:fedcba9876543210
> +n_tables:254, n_buffers:256
> +capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
> +actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
> + 1($1): addr:aa:55:aa:55:00:0x
> + config: PORT_DOWN
> + state: LINK_DOWN
> + speed: 0 Mbps now, 0 Mbps max
> + 2(n2): addr:aa:55:aa:55:00:0x
> + config: PORT_DOWN
> + state: LINK_DOWN
> + speed: 0 Mbps now, 0 Mbps max
> + LOCAL(br0): addr:aa:55:aa:55:00:0x
> + config: PORT_DOWN
> + state: LINK_DOWN
> + speed: 0 Mbps now, 0 Mbps max
> +OFPT_GET_CONFIG_REPLY: frags=normal miss_send_len=0"
> + AT_CHECK([[sed '
> +s/ (xid=0x[0-9a-fA-F]*)//
> +s/00:0.$/00:0x/' < stdout]],
> + [0], [expout])
> +}
> +
> +AT_CHECK([ovs-vsctl set Interface p1 ofname=p2])
> +check_ofname p2
> +
> +AT_CHECK([ovs-ofctl -P standard monitor br0 --detach --no-chdir --pidfile])
> +# Use NXT_SET_ASYNC_CONFIG to enable only port status message
> +ovs-appctl -t ovs-ofctl ofctl/send 01040028000000020000232000000013000000000000000500000007000000020000000000000005
> +ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
> +AT_CHECK([ovs-vsctl set Interface p1 ofname=n2])
> +check_ofname n2
> +OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
> +AT_CHECK([[sed '
> +s/ (xid=0x[0-9a-fA-F]*)//
> +s/ *duration.*//
> +s/00:0.$/00:0x/' < monitor.log]],
> + [0], [dnl
> +OFPT_PORT_STATUS: DEL: 1(p2): addr:aa:55:aa:55:00:0x
> + config: PORT_DOWN
> + state: LINK_DOWN
> + speed: 0 Mbps now, 0 Mbps max
> +OFPT_PORT_STATUS: ADD: 1(n2): addr:aa:55:aa:55:00:0x
> + config: PORT_DOWN
> + state: LINK_DOWN
> + speed: 0 Mbps now, 0 Mbps max
> +])
> +
> +AT_CHECK([ovs-vsctl clear Interface p1 ofname])
> +check_ofname p1
> +
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
> dnl This is really bare-bones.
> dnl It at least checks request and reply serialization and deserialization.
> AT_SETUP([ofproto - port stats - (OpenFlow 1.0)])
> diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
> index c9c0f6d..44b386a 100644
> --- a/utilities/ovs-vsctl.c
> +++ b/utilities/ovs-vsctl.c
> @@ -1008,6 +1008,7 @@ static struct cmd_show_table cmd_show_tables[] = {
> {&ovsrec_table_interface,
> &ovsrec_interface_col_name,
> {&ovsrec_interface_col_type,
> + &ovsrec_interface_col_ofname,
> &ovsrec_interface_col_options,
> &ovsrec_interface_col_error},
> {NULL, NULL, NULL}
> diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> index 700f65c..bb49fe0 100644
> --- a/vswitchd/bridge.c
> +++ b/vswitchd/bridge.c
> @@ -667,6 +667,10 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
>
> LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
> iface_set_ofport(iface->cfg, iface->ofp_port);
> +
> + ofproto_port_set_ofpname(br->ofproto, iface->ofp_port,
> + iface->cfg->ofname);
> +
> /* Clear eventual previous errors */
> ovsrec_interface_set_error(iface->cfg, NULL);
> iface_configure_cfm(iface);
> @@ -1777,7 +1781,8 @@ iface_do_create(const struct bridge *br,
> }
>
> *ofp_portp = iface_pick_ofport(iface_cfg);
> - error = ofproto_port_add(br->ofproto, netdev, ofp_portp);
> + error = ofproto_port_add(br->ofproto, netdev, ofp_portp,
> + iface_cfg->ofname);
> if (error) {
> goto error;
> }
> @@ -1860,7 +1865,8 @@ iface_create(struct bridge *br, const struct ovsrec_interface *iface_cfg,
> error = netdev_open(port->name, "internal", &netdev);
> if (!error) {
> ofp_port_t fake_ofp_port = OFPP_NONE;
> - ofproto_port_add(br->ofproto, netdev, &fake_ofp_port);
> + ofproto_port_add(br->ofproto, netdev, &fake_ofp_port,
> + iface_cfg->ofname);
> netdev_close(netdev);
> } else {
> VLOG_WARN("could not open network device %s (%s)",
> diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema
> index e0937f4..d147d04 100644
> --- a/vswitchd/vswitch.ovsschema
> +++ b/vswitchd/vswitch.ovsschema
> @@ -1,6 +1,6 @@
> {"name": "Open_vSwitch",
> - "version": "7.13.0",
> - "cksum": "2202834738 22577",
> + "version": "7.13.1",
> + "cksum": "643309718 22653",
> "tables": {
> "Open_vSwitch": {
> "columns": {
> @@ -204,6 +204,8 @@
> "mutable": false},
> "type": {
> "type": "string"},
> + "ofname": {
> + "type": {"key": "string", "min": 0, "max": 1}},
> "options": {
> "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}},
> "ingress_policing_rate": {
> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> index 166f264..1869c81 100644
> --- a/vswitchd/vswitch.xml
> +++ b/vswitchd/vswitch.xml
> @@ -1724,6 +1724,20 @@
> on a host.
> </column>
>
> +
> + <column name="ofname">
> + <p>
> + OpenFlow port name for this interface. This name is truncated to
> + <code>OFP_MAX_PORT_NAME_LEN-1</code>, and reported to controllers in
> + port description. If not set, <ref column='name'/> is used.
> + </p>
> + <p>
> + OpenFlow does not have a way to announce a port name change, so if
> + <ref column="ofname"/> is changed, Open vSwitch represents it over
> + OpenFlow as a port deletion followed immediately by a port addition.
> + </p>
> + </column>
> +
> <column name="ifindex">
> A positive interface index as defined for SNMP MIB-II in RFCs 1213 and
> 2863, if the interface has one, otherwise 0. The ifindex is useful for
> --
> 2.8.0
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
--
fbl
More information about the dev
mailing list