not work as expected.
*/
ifindex_t ifindex;
+ /*
+ * ifindex of parent interface, if any
+ */
+ ifindex_t link_ifindex;
#define IFINDEX_INTERNAL 0
/* Zebra internal interface status */
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | bandwidth |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | parent ifindex |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Link Layer Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Harware Address Length |
ifp->mtu = stream_getl(s);
ifp->mtu6 = stream_getl(s);
ifp->bandwidth = stream_getl(s);
+ ifp->link_ifindex = stream_getl(s);
ifp->ll_type = stream_getl(s);
ifp->hw_addr_len = stream_getl(s);
if (ifp->hw_addr_len)
/* Other ------------------------------------------------------------------- */
+static struct vrrp_vrouter *
+vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
+{
+ struct interface *p;
+ struct vrrp_vrouter *vr;
+
+ p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
+ uint8_t vrid = mvl_ifp->hw_addr[5];
+
+ zlog_info(VRRP_LOGPFX "Autoconfiguring VRRP on %s", p->name);
+
+ /* If it already exists, skip it */
+ vr = vrrp_lookup(p, vrid);
+ if (vr) {
+ zlog_info(VRRP_LOGPFX "VRRP instance %" PRIu8
+ "already configured on %s",
+ vrid, p->name);
+ return vr;
+ }
+
+ /* create a new one */
+ vr = vrrp_vrouter_create(p, vrid, vrrp_autoconfig_version);
+
+ if (!vr)
+ return NULL;
+
+ /* add connected addresses as vips */
+ struct listnode *ln;
+ struct connected *c = NULL;
+ for (ALL_LIST_ELEMENTS_RO(mvl_ifp->connected, ln, c))
+ if (c->address->family == AF_INET)
+ vrrp_add_ipv4(vr, c->address->u.prefix4, false);
+ else if (c->address->family == AF_INET6) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
+ vrrp_add_ipv6(vr, c->address->u.prefix6, false);
+ }
+
+ if (vr->v4->addrs->count)
+ vrrp_event(vr->v4, VRRP_EVENT_STARTUP);
+ if (vr->v6->addrs->count)
+ vrrp_event(vr->v6, VRRP_EVENT_STARTUP);
+
+ vr->autoconf = true;
+
+ return vr;
+}
+
+static bool vrrp_ifp_is_mvl(struct interface *ifp)
+{
+ struct ethaddr vmac4;
+ struct ethaddr vmac6;
+ vrrp_mac_set(&vmac4, 0, 0x00);
+ vrrp_mac_set(&vmac6, 1, 0x00);
+
+ return !memcmp(ifp->hw_addr, vmac4.octet, sizeof(vmac4.octet) - 1)
+ || !memcmp(ifp->hw_addr, vmac6.octet, sizeof(vmac6.octet) - 1);
+}
+
+int vrrp_autoconfig(struct interface *ifp)
+{
+ if (ifp && vrrp_ifp_is_mvl(ifp)) {
+ vrrp_autoconfig_autocreate(ifp);
+ return 0;
+ }
+
+ /* Loop through interfaces, looking for compatible macvlan devices. */
+ struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+
+ FOR_ALL_INTERFACES (vrf, ifp)
+ if (vrrp_ifp_is_mvl(ifp))
+ vrrp_autoconfig_autocreate(ifp);
+
+ return 0;
+}
+
static unsigned int vrrp_hash_key(void *arg)
{
struct vrrp_vrouter *vr = arg;
void vrrp_init(void)
{
+ vrrp_autoconfig_version = 3;
vrrp_vrouters_hash = hash_create(&vrrp_hash_key, vrrp_hash_cmp,
"VRRP virtual router hash");
vrf_init(NULL, NULL, NULL, NULL, NULL);
/* Global hash of all Virtual Routers */
struct hash *vrrp_vrouters_hash;
-/*
- * VRRP Router.
- *
- * This struct contains all state for a particular VRRP Router operating in a
- * Virtual Router for either IPv4 or IPv6.
- */
-struct vrrp_router {
+/* Whether to automatically configure VRRP instances */
+static bool vrrp_autoconfig_on;
+static int vrrp_autoconfig_version;
+
+ /*
+ * VRRP Router.
+ *
+ * This struct contains all state for a particular VRRP Router operating
+ * in a Virtual Router for either IPv4 or IPv6.
+ */
+ struct vrrp_router {
/*
* Whether this VRRP Router is active.
*/
* implementations.
*/
struct vrrp_vrouter {
+ /* Whether this instance was automatically configured */
+ bool autoconf;
+
/* Interface */
struct interface *ifp;
/* Other ------------------------------------------------------------------- */
+/*
+ * Search for and automatically configure VRRP instances on interfaces.
+ *
+ * ifp
+ * Interface to autoconfig. If it is a macvlan interface and has a VRRP MAC,
+ * a VRRP instance corresponding to VMAC assigned to macvlan will be created
+ * on the parent interface and all addresses on the macvlan interface except
+ * the v6 link local will be configured as VRRP addresses. If NULL, this
+ * treatment will be applied to all existing interfaces matching the above
+ * criterion.
+ *
+ * Returns:
+ * -1 on failure
+ * 0 otherwise
+ */
+int vrrp_autoconfig(struct interface *ifp);
+
/*
* Find VRRP Virtual Router by Virtual Router ID
*/
return CMD_SUCCESS;
}
+DEFPY(vrrp_autoconf,
+ vrrp_autoconf_cmd,
+ "[no] vrrp autoconfig [version (2-3)]",
+ NO_STR
+ VRRP_STR
+ "Automatically set up VRRP instances on VRRP-compatible interfaces\n"
+ "Version for automatically configured instances\n"
+ VRRP_VERSION_STR)
+{
+ vrrp_autoconfig_on = !no;
+ version = version ? version : 3;
+
+ if (vrrp_autoconfig_on)
+ vrrp_autoconfig(NULL);
+
+ vrrp_autoconfig_version = !no ? version : vrrp_autoconfig_version;
+
+ return CMD_SUCCESS;
+}
+
static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
{
char ethstr4[ETHER_ADDR_STRLEN];
if_cmd_init();
install_element(VIEW_NODE, &show_debugging_vrrpd_cmd);
install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
+ install_element(CONFIG_NODE, &vrrp_autoconf_cmd);
install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
install_element(INTERFACE_NODE, &vrrp_priority_cmd);
install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
if (!ifp)
return 0;
- /* FIXME: handle subinterface creation here */
+ if (vrrp_autoconfig_on)
+ vrrp_autoconfig(ifp);
return 0;
}
static void zserv_encode_interface(struct stream *s, struct interface *ifp)
{
/* Interface information. */
+ struct zebra_if *zif = ifp->info;
stream_put(s, ifp->name, INTERFACE_NAMSIZ);
stream_putl(s, ifp->ifindex);
stream_putc(s, ifp->status);
stream_putl(s, ifp->mtu);
stream_putl(s, ifp->mtu6);
stream_putl(s, ifp->bandwidth);
+ stream_putl(s, zif->link_ifindex);
stream_putl(s, ifp->ll_type);
stream_putl(s, ifp->hw_addr_len);
if (ifp->hw_addr_len)