- error = netdev_create(iface_cfg->name, iface_cfg->type, &options);
- } else {
- /* xxx Check to make sure that the type hasn't changed. */
- error = netdev_reconfigure(iface_cfg->name, &options);
+ struct netdev_options netdev_options;
+
+ memset(&netdev_options, 0, sizeof netdev_options);
+ netdev_options.name = iface_cfg->name;
+ if (!strcmp(iface_cfg->type, "internal")) {
+ /* An "internal" config type maps to a netdev "system" type. */
+ netdev_options.type = "system";
+ } else {
+ netdev_options.type = iface_cfg->type;
+ }
+ netdev_options.args = &options;
+ netdev_options.ethertype = NETDEV_ETH_TYPE_NONE;
+ netdev_options.may_create = true;
+ if (iface_is_internal(iface->port->bridge, iface_cfg->name)) {
+ netdev_options.may_open = true;
+ }
+
+ error = netdev_open(&netdev_options, &iface->netdev);
+
+ if (iface->netdev) {
+ netdev_get_carrier(iface->netdev, &iface->enabled);
+ }
+ } else if (iface->netdev) {
+ const char *netdev_type = netdev_get_type(iface->netdev);
+ const char *iface_type = iface_cfg->type && strlen(iface_cfg->type)
+ ? iface_cfg->type : NULL;
+
+ /* An "internal" config type maps to a netdev "system" type. */
+ if (iface_type && !strcmp(iface_type, "internal")) {
+ iface_type = "system";
+ }
+
+ if (!iface_type || !strcmp(netdev_type, iface_type)) {
+ error = netdev_reconfigure(iface->netdev, &options);
+ } else {
+ VLOG_WARN("%s: attempting change device type from %s to %s",
+ iface_cfg->name, netdev_type, iface_type);
+ error = EINVAL;
+ }