return false;
}
+/*
+ * Sorting of assignment entries:
+ * Primary on assignment length: smallest assignment first
+ * Secondary on assignment weight: highest weight first
+ * Finally alphabetical order of interface names
+ */
+static int prefix_assignment_cmp(const void *k1, const void *k2, void *ptr)
+{
+ const struct device_prefix_assignment *a1 = k1, *a2 = k2;
+
+ if (a1->length != a2->length)
+ return a1->length - a2->length;
+
+ if (a1->weight != a2->weight)
+ return a2->weight - a1->weight;
+
+ return strcmp(a1->name, a2->name);
+}
+
static void interface_update_prefix_assignments(struct device_prefix *prefix, bool setup)
{
struct device_prefix_assignment *c;
}
bool assigned_any = false;
- struct list_head assign_later = LIST_HEAD_INIT(assign_later);
+ struct {
+ struct avl_node node;
+ } *entry, *n_entry;
+ struct avl_tree assign_later;
+
+ avl_init(&assign_later, prefix_assignment_cmp, false, NULL);
+
vlist_for_each_element(&interfaces, iface, node) {
if (iface->assignment_length < 48 ||
iface->assignment_length > 64)
c->length = iface->assignment_length;
c->assigned = iface->assignment_hint;
+ c->weight = iface->assignment_weight;
c->addr = in6addr_any;
c->enabled = false;
memcpy(c->name, iface->name, namelen);
"of size %hhu for %s, trying other\n", c->length, c->name);
}
- struct list_head *next = &assign_later;
- struct device_prefix_assignment *n;
- list_for_each_entry(n, &assign_later, head) {
- if (n->length < c->length) {
- next = &n->head;
- break;
- }
- }
- list_add_tail(&c->head, next);
+ entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ continue;
+
+ entry->node.key = c;
+ avl_insert(&assign_later, &entry->node);
}
if (c->assigned != -1)
assigned_any = true;
}
- // Then try to assign all other + failed custom assignments
- while (!list_empty(&assign_later)) {
- c = list_first_entry(&assign_later, struct device_prefix_assignment, head);
- list_del(&c->head);
-
+ /* Then try to assign all other + failed custom assignments */
+ avl_for_each_element_safe(&assign_later, entry, node, n_entry) {
bool assigned = false;
+
+ c = (struct device_prefix_assignment *)entry->node.key;
+ avl_delete(&assign_later, &entry->node);
+
do {
assigned = interface_prefix_assign(&prefix->assignments, c);
} while (!assigned && ++c->length <= 64);
netifd_log_message(L_WARNING, "Failed to assign subprefix "
"of size %hhu for %s\n", c->length, c->name);
free(c);
- } else {
+ } else
assigned_any = true;
- }
+
+ free(entry);
}
list_for_each_entry(c, &prefix->assignments, head)
list_for_each_entry(c, &prefix_new->assignments, head)
if ((iface = vlist_find(&interfaces, c->name, iface, node)))
interface_set_prefix_address(c, prefix_new, iface, true);
+
+ if (prefix_new->preferred_until != prefix_old->preferred_until ||
+ prefix_new->valid_until != prefix_old->valid_until)
+ ip->iface->updated |= IUF_PREFIX;
} else if (node_new) {
// Set null-route to avoid routing loops
system_add_route(NULL, &route);
avl_for_each_element(&resolv_conf_iface_entries, entry, node) {
iface = (struct interface *)entry->node.key;
+ struct device *dev = iface->l3_dev.dev;
fprintf(f, "# Interface %s\n", iface->name);
- write_resolv_conf_entries(f, &iface->config_ip, iface->ifname);
+ write_resolv_conf_entries(f, &iface->config_ip, dev->ifname);
if (!iface->proto_ip.no_dns)
- write_resolv_conf_entries(f, &iface->proto_ip, iface->ifname);
+ write_resolv_conf_entries(f, &iface->proto_ip, dev->ifname);
}
avl_remove_all_elements(&resolv_conf_iface_entries, entry, node, n_entry)