IFACE_ATTR_DELEGATE,
IFACE_ATTR_IP6IFACEID,
IFACE_ATTR_FORCE_LINK,
+ IFACE_ATTR_IP6WEIGHT,
IFACE_ATTR_MAX
};
[IFACE_ATTR_DELEGATE] = { .name = "delegate", .type = BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_IP6IFACEID] = { .name = "ip6ifaceid", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_FORCE_LINK] = { .name = "force_link", .type = BLOBMSG_TYPE_BOOL },
+ [IFACE_ATTR_IP6WEIGHT] = { .name = "ip6weight", .type = BLOBMSG_TYPE_INT32 },
};
const struct uci_blob_param_list interface_attr_list = {
adev = iface->l3_dev.dev;
/* fall through */
case IFEV_DOWN:
+ case IFEV_UP_FAILED:
alias_notify_device(iface->name, adev);
break;
default:
iface->link_up_event = false;
iface->state = IFS_DOWN;
- if (state == IFS_UP)
+ switch (state) {
+ case IFS_UP:
interface_event(iface, IFEV_DOWN);
+ break;
+ case IFS_SETUP:
+ interface_event(iface, IFEV_UP_FAILED);
+ break;
+ default:
+ break;
+ }
interface_ip_set_enabled(&iface->config_ip, false);
interface_ip_set_enabled(&iface->proto_ip, false);
interface_ip_flush(&iface->proto_ip);
system_flush_routes();
}
-void
+static void
__interface_set_down(struct interface *iface, bool force)
{
enum interface_state state = iface->state;
interface_main_dev_cb(struct device_user *dep, enum device_event ev)
{
struct interface *iface;
- bool new_state = false;
iface = container_of(dep, struct interface, main_dev);
switch (ev) {
case DEV_EVENT_ADD:
- new_state = true;
+ interface_set_available(iface, true);
+ break;
case DEV_EVENT_REMOVE:
- interface_set_available(iface, new_state);
- if (!new_state && dep->dev && dep->dev->external)
+ interface_set_available(iface, false);
+ if (dep->dev && dep->dev->external)
interface_set_main_dev(iface, NULL);
break;
case DEV_EVENT_UP:
- new_state = true;
+ interface_set_enabled(iface, true);
+ break;
case DEV_EVENT_DOWN:
- interface_set_enabled(iface, new_state);
+ interface_set_enabled(iface, false);
break;
case DEV_EVENT_LINK_UP:
- new_state = true;
+ interface_set_link_state(iface, true);
+ break;
case DEV_EVENT_LINK_DOWN:
- interface_set_link_state(iface, new_state);
+ interface_set_link_state(iface, false);
break;
case DEV_EVENT_TOPO_CHANGE:
interface_proto_event(iface->proto, PROTO_CMD_RENEW, false);
bool changed = (old->assignment_hint != new->assignment_hint ||
old->assignment_length != new->assignment_length ||
old->assignment_iface_id_selection != new->assignment_iface_id_selection ||
+ old->assignment_weight != new->assignment_weight ||
(old->assignment_iface_id_selection == IFID_FIXED &&
memcmp(&old->assignment_fixed_iface_id, &new->assignment_fixed_iface_id,
sizeof(old->assignment_fixed_iface_id))) ||
old->assignment_length = new->assignment_length;
old->assignment_iface_id_selection = new->assignment_iface_id_selection;
old->assignment_fixed_iface_id = new->assignment_fixed_iface_id;
+ old->assignment_weight = new->assignment_weight;
interface_refresh_assignments(true);
}
}
interface_set_available(alias, true);
break;
case IFEV_DOWN:
+ case IFEV_UP_FAILED:
interface_set_available(alias, false);
interface_set_main_dev(alias, NULL);
break;
interface_do_free(iface);
return;
}
- if (iface->autostart && iface->available)
+ if (iface->autostart)
interface_set_up(iface);
else if (iface->dynamic)
set_config_state(iface, IFC_REMOVE);
if ((cur = tb[IFACE_ATTR_IP6CLASS]))
interface_add_assignment_classes(iface, cur);
+ if ((cur = tb[IFACE_ATTR_IP6WEIGHT]))
+ iface->assignment_weight = blobmsg_get_u32(cur);
if ((cur = tb[IFACE_ATTR_IP4TABLE])) {
if (!system_resolve_rt_table(blobmsg_data(cur), &iface->ip4table))
return ret;
}
-int
+void
interface_set_up(struct interface *iface)
{
int ret;
+ const char *error = NULL;
iface->autostart = true;
if (iface->state != IFS_DOWN)
- return 0;
+ return;
interface_clear_errors(iface);
- if (!iface->available) {
- interface_add_error(iface, "interface", "NO_DEVICE", NULL, 0);
- return -1;
- }
-
- if (iface->main_dev.dev) {
- ret = device_claim(&iface->main_dev);
- if (!ret)
- interface_check_state(iface);
- }
- else
- ret = __interface_set_up(iface);
+ if (iface->available) {
+ if (iface->main_dev.dev) {
+ ret = device_claim(&iface->main_dev);
+ if (!ret)
+ interface_check_state(iface);
+ else
+ error = "DEVICE_CLAIM_FAILED";
+ } else {
+ ret = __interface_set_up(iface);
+ if (ret)
+ error = "SETUP_FAILED";
+ }
+ } else
+ error = "NO_DEVICE";
- return ret;
+ if (error)
+ interface_add_error(iface, "interface", error, NULL, 0);
}
-int
+void
interface_set_down(struct interface *iface)
{
if (!iface) {
iface->autostart = false;
__interface_set_down(iface, false);
}
+}
- return 0;
+int
+interface_renew(struct interface *iface)
+{
+ if (iface->state == IFS_TEARDOWN || iface->state == IFS_DOWN)
+ return -1;
+
+ return interface_proto_event(iface->proto, PROTO_CMD_RENEW, false);
}
void
struct interface *iface;
vlist_for_each_element(&interfaces, iface, node) {
- if (iface->available && iface->autostart)
+ if (iface->autostart)
interface_set_up(iface);
}
}
set_config_state(if_old, IFC_REMOVE);
} else if (node_new) {
D(INTERFACE, "Create interface '%s'\n", if_new->name);
+ interface_event(if_new, IFEV_CREATE);
proto_init_interface(if_new, if_new->config);
interface_claim_device(if_new);
netifd_ubus_add_interface(if_new);