• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/netifd/vrf.c

  1 #include <string.h>
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <assert.h>
  5 
  6 #include "netifd.h"
  7 #include "device.h"
  8 #include "system.h"
  9 
 10 enum {
 11         VRF_ATTR_PORTS,
 12         VRF_ATTR_TABLE,
 13         __VRF_ATTR_MAX
 14 };
 15 
 16 static const struct blobmsg_policy vrf_attrs[__VRF_ATTR_MAX] = {
 17         [VRF_ATTR_PORTS] = { "ports", BLOBMSG_TYPE_ARRAY },
 18         [VRF_ATTR_TABLE] = { "table", BLOBMSG_TYPE_STRING },
 19 };
 20 
 21 static const struct uci_blob_param_info vrf_attr_info[__VRF_ATTR_MAX] = {
 22         [VRF_ATTR_PORTS] = { .type = BLOBMSG_TYPE_STRING },
 23 };
 24 
 25 static const struct uci_blob_param_list vrf_attr_list = {
 26         .n_params = __VRF_ATTR_MAX,
 27         .params = vrf_attrs,
 28         .info = vrf_attr_info,
 29 
 30         .n_next = 1,
 31         .next = { &device_attr_list },
 32 };
 33 
 34 static struct device *vrf_create(const char *name, struct device_type *devtype,
 35         struct blob_attr *attr);
 36 static void vrf_config_init(struct device *dev);
 37 static void vrf_free(struct device *dev);
 38 static void vrf_dump_info(struct device *dev, struct blob_buf *b);
 39 static enum dev_change_type
 40 vrf_reload(struct device *dev, struct blob_attr *attr);
 41 
 42 static struct device_type vrf_state_type = {
 43         .name = "vrf",
 44         .config_params = &vrf_attr_list,
 45 
 46         .bridge_capability = true,
 47 
 48         .create = vrf_create,
 49         .config_init = vrf_config_init,
 50         .reload = vrf_reload,
 51         .free = vrf_free,
 52         .dump_info = vrf_dump_info,
 53 };
 54 
 55 struct vrf_state {
 56         struct device dev;
 57         device_state_cb set_state;
 58 
 59         struct blob_attr *config_data;
 60         unsigned int table;
 61         bool vrf_empty;
 62         struct blob_attr *ports;
 63         bool active;
 64         bool force_active;
 65 
 66         struct uloop_timeout retry;
 67         struct vrf_member *primary_port;
 68         struct vlist_tree members;
 69         int n_present;
 70         int n_failed;
 71 };
 72 
 73 struct vrf_member {
 74         struct vlist_node node;
 75         struct vrf_state *vst;
 76         struct device_user dev;
 77         bool present;
 78         bool active;
 79         char name[];
 80 };
 81 
 82 static void
 83 vrf_reset_primary(struct vrf_state *vst)
 84 {
 85         struct vrf_member *vm;
 86 
 87         if (!vst->primary_port &&
 88                 (vst->dev.settings.flags & DEV_OPT_MACADDR))
 89                 return;
 90 
 91         vst->primary_port = NULL;
 92         vst->dev.settings.flags &= ~DEV_OPT_MACADDR;
 93         vlist_for_each_element(&vst->members, vm, node) {
 94                 uint8_t *macaddr;
 95 
 96                 if (!vm->present)
 97                         continue;
 98 
 99                 vst->primary_port = vm;
100                 if (vm->dev.dev->settings.flags & DEV_OPT_MACADDR)
101                         macaddr = vm->dev.dev->settings.macaddr;
102                 else
103                         macaddr = vm->dev.dev->orig_settings.macaddr;
104                 memcpy(vst->dev.settings.macaddr, macaddr, 6);
105                 vst->dev.settings.flags |= DEV_OPT_MACADDR;
106                 return;
107         }
108 }
109 
110 static int
111 vrf_disable_member(struct vrf_member *vm, bool keep_dev)
112 {
113         struct vrf_state *vst = vm->vst;
114 
115         if (!vm->present || !vm->active)
116                 return 0;
117 
118         vm->active = false;
119 
120         system_vrf_delif(&vst->dev, vm->dev.dev);
121         if (!keep_dev)
122                 device_release(&vm->dev);
123 
124         device_broadcast_event(&vst->dev, DEV_EVENT_TOPO_CHANGE);
125 
126         return 0;
127 }
128 
129 static int
130 vrf_enable_interface(struct vrf_state *vst)
131 {
132         int ret;
133 
134         if (vst->active)
135                 return 0;
136 
137         ret = system_vrf_addvrf(&vst->dev, vst->table);
138         if (ret < 0)
139                 return ret;
140 
141         vst->active = true;
142         return 0;
143 }
144 
145 static void
146 vrf_disable_interface(struct vrf_state *vst)
147 {
148         if (!vst->active)
149                 return;
150 
151         system_vrf_delvrf(&vst->dev);
152         vst->active = false;
153 }
154 
155 static int
156 vrf_enable_member(struct vrf_member *vm)
157 {
158         struct vrf_state *vst = vm->vst;
159         struct device *dev;
160         int ret;
161 
162         if (!vm->present)
163                 return 0;
164 
165         ret = vrf_enable_interface(vst);
166         if (ret)
167                 goto error;
168 
169         /* Disable IPv6 for vrf ports */
170         if (!(vm->dev.dev->settings.flags & DEV_OPT_IPV6)) {
171                 vm->dev.dev->settings.ipv6 = 0;
172                 vm->dev.dev->settings.flags |= DEV_OPT_IPV6;
173         }
174 
175         ret = device_claim(&vm->dev);
176         if (ret < 0)
177                 goto error;
178 
179         dev = vm->dev.dev;
180         if (dev->settings.auth && !dev->auth_status)
181                 return -1;
182 
183         if (vm->active)
184                 return 0;
185 
186         ret = system_vrf_addif(&vst->dev, vm->dev.dev);
187         if (ret < 0) {
188                 D(DEVICE, "Vrf device %s could not be added\n", vm->dev.dev->ifname);
189                 goto error;
190         }
191 
192         vm->active = true;
193         device_set_present(&vst->dev, true);
194         device_broadcast_event(&vst->dev, DEV_EVENT_TOPO_CHANGE);
195 
196         return 0;
197 
198 error:
199         vst->n_failed++;
200         vm->present = false;
201         vst->n_present--;
202         device_release(&vm->dev);
203 
204         return ret;
205 }
206 
207 static void
208 vrf_remove_member(struct vrf_member *vm)
209 {
210         struct vrf_state *vst = vm->vst;
211 
212         if (!vm->present)
213                 return;
214 
215         if (vst->dev.active)
216                 vrf_disable_member(vm, false);
217 
218         vm->present = false;
219         vm->vst->n_present--;
220 
221         if (vm == vst->primary_port)
222                 vrf_reset_primary(vst);
223 
224         if (vst->vrf_empty)
225                 return;
226 
227         vst->force_active = false;
228         if (vst->n_present == 0)
229                 device_set_present(&vst->dev, false);
230 }
231 
232 static void
233 vrf_free_member(struct vrf_member *vm)
234 {
235         struct device *dev = vm->dev.dev;
236 
237         vrf_remove_member(vm);
238         device_remove_user(&vm->dev);
239 
240         /*
241          * When reloading the config and moving a device from one vrf to
242          * another, the other vrf may have tried to claim this device
243          * before it was removed here.
244          * Ensure that claiming the device is retried by toggling its present
245          * state
246          */
247         if (dev->present) {
248                 device_set_present(dev, false);
249                 device_set_present(dev, true);
250         }
251 
252         free(vm);
253 }
254 
255 static void
256 vrf_check_retry(struct vrf_state *vst)
257 {
258         if (!vst->n_failed)
259                 return;
260 
261         uloop_timeout_set(&vst->retry, 100);
262 }
263 
264 static void
265 vrf_member_cb(struct device_user *dep, enum device_event ev)
266 {
267         struct vrf_member *vm = container_of(dep, struct vrf_member, dev);
268         struct vrf_state *vst = vm->vst;
269         struct device *dev = dep->dev;
270 
271         switch (ev) {
272         case DEV_EVENT_ADD:
273                 assert(!vm->present);
274 
275                 vm->present = true;
276                 vst->n_present++;
277 
278                 if (vst->n_present == 1)
279                         device_set_present(&vst->dev, true);
280                 fallthrough;
281         case DEV_EVENT_AUTH_UP:
282                 if (!vst->dev.active)
283                         break;
284 
285                 if (vrf_enable_member(vm))
286                         break;
287 
288                 /*
289                  * Adding a vrf port can overwrite the vrf device mtu
290                  * in the kernel, apply the vrf settings in case the
291                  * vrf device mtu is set
292                  */
293                 system_if_apply_settings(&vst->dev, &vst->dev.settings,
294                                          DEV_OPT_MTU | DEV_OPT_MTU6);
295                 break;
296         case DEV_EVENT_LINK_DOWN:
297                 if (!dev->settings.auth)
298                         break;
299 
300                 vrf_disable_member(vm, true);
301                 break;
302         case DEV_EVENT_REMOVE:
303                 if (dep->hotplug && !dev->sys_present) {
304                         vlist_delete(&vst->members, &vm->node);
305                         return;
306                 }
307 
308                 if (vm->present)
309                         vrf_remove_member(vm);
310 
311                 break;
312         default:
313                 return;
314         }
315 }
316 
317 static int
318 vrf_set_down(struct vrf_state *vst)
319 {
320         struct vrf_member *vm;
321 
322         vst->set_state(&vst->dev, false);
323 
324         vlist_for_each_element(&vst->members, vm, node)
325                 vrf_disable_member(vm, false);
326 
327         vrf_disable_interface(vst);
328 
329         return 0;
330 }
331 
332 static int
333 vrf_set_up(struct vrf_state *vst)
334 {
335         struct vrf_member *vm;
336         int ret;
337 
338         if (!vst->n_present) {
339                 if (!vst->force_active)
340                         return -ENOENT;
341 
342                 ret = vrf_enable_interface(vst);
343                 if (ret)
344                         return ret;
345         }
346 
347         vst->n_failed = 0;
348         vlist_for_each_element(&vst->members, vm, node)
349                 vrf_enable_member(vm);
350         vrf_check_retry(vst);
351 
352         if (!vst->force_active && !vst->n_present) {
353                 /* initialization of all port member failed */
354                 vrf_disable_interface(vst);
355                 device_set_present(&vst->dev, false);
356                 return -ENOENT;
357         }
358 
359         vrf_reset_primary(vst);
360         ret = vst->set_state(&vst->dev, true);
361         if (ret < 0)
362                 vrf_set_down(vst);
363 
364         return ret;
365 }
366 
367 static int
368 vrf_set_state(struct device *dev, bool up)
369 {
370         struct vrf_state *vst;
371 
372         vst = container_of(dev, struct vrf_state, dev);
373 
374         if (up)
375                 return vrf_set_up(vst);
376         else
377                 return vrf_set_down(vst);
378 }
379 
380 static struct vrf_member *
381 vrf_create_member(struct vrf_state *vst, const char *name,
382                         struct device *dev, bool hotplug)
383 {
384         struct vrf_member *vm;
385 
386         vm = calloc(1, sizeof(*vm) + strlen(name) + 1);
387         if (!vm)
388                 return NULL;
389 
390         vm->vst = vst;
391         vm->dev.cb = vrf_member_cb;
392         vm->dev.hotplug = hotplug;
393         strcpy(vm->name, name);
394         vm->dev.dev = dev;
395         vlist_add(&vst->members, &vm->node, vm->name);
396         /*
397          * Need to look up the vrf port again as the above
398          * created pointer will be freed in case the vrf port
399          * already existed
400          */
401         vm = vlist_find(&vst->members, name, vm, node);
402         if (hotplug && vm)
403                 vm->node.version = -1;
404 
405         return vm;
406 }
407 
408 static void
409 vrf_member_update(struct vlist_tree *tree, struct vlist_node *node_new,
410                          struct vlist_node *node_old)
411 {
412         struct vrf_member *vm;
413         struct device *dev;
414 
415         if (node_new) {
416                 vm = container_of(node_new, struct vrf_member, node);
417 
418                 if (node_old) {
419                         free(vm);
420                         return;
421                 }
422 
423                 dev = vm->dev.dev;
424                 vm->dev.dev = NULL;
425                 device_add_user(&vm->dev, dev);
426         }
427 
428 
429         if (node_old) {
430                 vm = container_of(node_old, struct vrf_member, node);
431                 vrf_free_member(vm);
432         }
433 }
434 
435 static void
436 vrf_add_member(struct vrf_state *vst, const char *name)
437 {
438         struct device *dev;
439 
440         dev = device_get(name, true);
441         if (!dev)
442                 return;
443 
444         vrf_create_member(vst, name, dev, false);
445 }
446 
447 static int
448 vrf_hotplug_add(struct device *dev, struct device *member, struct blob_attr *vlan)
449 {
450         struct vrf_state *vst = container_of(dev, struct vrf_state, dev);
451         struct vrf_member *vm;
452 
453         vm = vlist_find(&vst->members, member->ifname, vm, node);
454         if (!vm)
455                 vrf_create_member(vst, member->ifname, member, true);
456 
457         return 0;
458 }
459 
460 static int
461 vrf_hotplug_del(struct device *dev, struct device *member, struct blob_attr *vlan)
462 {
463         struct vrf_state *vst = container_of(dev, struct vrf_state, dev);
464         struct vrf_member *vm;
465 
466         vm = vlist_find(&vst->members, member->ifname, vm, node);
467         if (!vm)
468                 return UBUS_STATUS_NOT_FOUND;
469 
470         if (vm->dev.hotplug)
471                 vlist_delete(&vst->members, &vm->node);
472 
473         return 0;
474 }
475 
476 static int
477 vrf_hotplug_prepare(struct device *dev, struct device **vrf_dev)
478 {
479         struct vrf_state *vst;
480 
481         if (vrf_dev)
482                 *vrf_dev = dev;
483 
484         vst = container_of(dev, struct vrf_state, dev);
485         vst->force_active = true;
486         device_set_present(&vst->dev, true);
487 
488         return 0;
489 }
490 
491 static const struct device_hotplug_ops vrf_ops = {
492         .prepare = vrf_hotplug_prepare,
493         .add = vrf_hotplug_add,
494         .del = vrf_hotplug_del
495 };
496 
497 static void
498 vrf_free(struct device *dev)
499 {
500         struct vrf_state *vst;
501 
502         vst = container_of(dev, struct vrf_state, dev);
503         vlist_flush_all(&vst->members);
504         free(vst->config_data);
505         free(vst);
506 }
507 
508 static void
509 vrf_dump_info(struct device *dev, struct blob_buf *b)
510 {
511         struct vrf_state *vst;
512         struct vrf_member *vm;
513         void *list;
514 
515         vst = container_of(dev, struct vrf_state, dev);
516 
517         system_if_dump_info(dev, b);
518         list = blobmsg_open_array(b, "vrf-members");
519 
520         vlist_for_each_element(&vst->members, vm, node) {
521                 if (vm->dev.dev->hidden)
522                         continue;
523 
524                 blobmsg_add_string(b, NULL, vm->dev.dev->ifname);
525         }
526 
527         blobmsg_close_array(b, list);
528 }
529 
530 static void
531 vrf_config_init(struct device *dev)
532 {
533         struct vrf_state *vst;
534         struct blob_attr *cur;
535         size_t rem;
536 
537         vst = container_of(dev, struct vrf_state, dev);
538 
539         if (vst->vrf_empty) {
540                 vst->force_active = true;
541                 device_set_present(&vst->dev, true);
542         }
543 
544         vst->n_failed = 0;
545         vlist_update(&vst->members);
546         if (vst->ports) {
547                 blobmsg_for_each_attr(cur, vst->ports, rem) {
548                         vrf_add_member(vst, blobmsg_data(cur));
549                 }
550         }
551 
552         vlist_flush(&vst->members);
553         vrf_check_retry(vst);
554 }
555 
556 static void
557 vrf_apply_settings(struct vrf_state *vst, struct blob_attr **tb)
558 {
559         struct blob_attr *cur;
560 
561         vst->vrf_empty = true;
562         // default vrf routing table
563         vst->table = 10;
564         if ((cur = tb[VRF_ATTR_TABLE]))
565                 system_resolve_rt_table(blobmsg_data(cur), &vst->table);
566 }
567 
568 static enum dev_change_type
569 vrf_reload(struct device *dev, struct blob_attr *attr)
570 {
571         struct blob_attr *tb_dev[__DEV_ATTR_MAX];
572         struct blob_attr *tb_v[__VRF_ATTR_MAX];
573         enum dev_change_type ret = DEV_CONFIG_APPLIED;
574         struct vrf_state *vst;
575         unsigned long diff[2];
576 
577         BUILD_BUG_ON(sizeof(diff) < __VRF_ATTR_MAX / BITS_PER_LONG);
578         BUILD_BUG_ON(sizeof(diff) < __DEV_ATTR_MAX / BITS_PER_LONG);
579 
580         vst = container_of(dev, struct vrf_state, dev);
581         attr = blob_memdup(attr);
582 
583         blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev,
584                 blob_data(attr), blob_len(attr));
585         blobmsg_parse(vrf_attrs, __VRF_ATTR_MAX, tb_v,
586                 blob_data(attr), blob_len(attr));
587 
588         if (tb_dev[DEV_ATTR_MACADDR])
589                 vst->primary_port = NULL;
590 
591         vst->ports = tb_v[VRF_ATTR_PORTS];
592         device_init_settings(dev, tb_dev);
593         vrf_apply_settings(vst, tb_v);
594 
595         if (vst->config_data) {
596                 struct blob_attr *otb_dev[__DEV_ATTR_MAX];
597                 struct blob_attr *otb_v[__VRF_ATTR_MAX];
598 
599                 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev,
600                         blob_data(vst->config_data), blob_len(vst->config_data));
601 
602                 diff[0] = diff[1] = 0;
603                 uci_blob_diff(tb_dev, otb_dev, &device_attr_list, diff);
604                 if (diff[0] | diff[1]) {
605                         ret = DEV_CONFIG_RESTART;
606                         D(DEVICE, "Vrf %s device attributes have changed, diff=[%lx %lx]\n",
607                           dev->ifname, diff[1], diff[0]);
608                 }
609 
610                 blobmsg_parse(vrf_attrs, __VRF_ATTR_MAX, otb_v,
611                         blob_data(vst->config_data), blob_len(vst->config_data));
612 
613                 diff[0] = diff[1] = 0;
614                 uci_blob_diff(tb_v, otb_v, &vrf_attr_list, diff);
615                 if (diff[0] & ~(1 << VRF_ATTR_PORTS)) {
616                         ret = DEV_CONFIG_RESTART;
617                         D(DEVICE, "Vrf %s attributes have changed, diff=[%lx %lx]\n",
618                           dev->ifname, diff[1], diff[0]);
619                 }
620 
621                 vrf_config_init(dev);
622         }
623 
624         free(vst->config_data);
625         vst->config_data = attr;
626         return ret;
627 }
628 
629 static void
630 vrf_retry_members(struct uloop_timeout *timeout)
631 {
632         struct vrf_state *vst = container_of(timeout, struct vrf_state, retry);
633         struct vrf_member *vm;
634 
635         vst->n_failed = 0;
636         vlist_for_each_element(&vst->members, vm, node) {
637                 if (vm->present)
638                         continue;
639 
640                 if (!vm->dev.dev->present)
641                         continue;
642 
643                 vm->present = true;
644                 vst->n_present++;
645                 vrf_enable_member(vm);
646         }
647 }
648 
649 static struct device *
650 vrf_create(const char *name, struct device_type *devtype,
651         struct blob_attr *attr)
652 {
653         struct vrf_state *vst;
654         struct device *dev = NULL;
655 
656         vst = calloc(1, sizeof(*vst));
657         if (!vst)
658                 return NULL;
659 
660         dev = &vst->dev;
661 
662         if (device_init(dev, devtype, name) < 0) {
663                 device_cleanup(dev);
664                 free(vst);
665                 return NULL;
666         }
667 
668         dev->config_pending = true;
669         vst->retry.cb = vrf_retry_members;
670 
671         vst->set_state = dev->set_state;
672         dev->set_state = vrf_set_state;
673 
674         dev->hotplug_ops = &vrf_ops;
675 
676         vlist_init(&vst->members, avl_strcmp, vrf_member_update);
677         vst->members.keep_old = true;
678 
679         vrf_reload(dev, attr);
680 
681         return dev;
682 }
683 
684 static void __init vrf_state_type_init(void)
685 {
686         device_type_add(&vrf_state_type);
687 }
688 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt