Skip to content

Extend shared/vnic.ksh to support creating vrrp vnics #375

@sjorge

Description

@sjorge

Currently it's not possible to have a brand automatically create vrrp vnics:

dladm create-vnic -m vrrp -l ixgbe0 -V 98 -A inet -v 110 ldap1vip0

I had a look at shared/vnic.ksh and it seems like it should be possible to add this without too much trouble but I am not sure this is the best approach, I'd like some feedback before further fleshing this out.

I was thinking something along the lines of:

--- a	2021-12-12 22:48:29.000000000 +0100
+++ b	2021-12-12 22:58:04.000000000 +0100
@@ -1,5 +1,5 @@
 function config_vnics {
-        demand_vnics | while read nic global mac vlan addr; do
+        demand_vnics | while read nic global mac vlan addr vrid vridfamily; do
                 [ -n "$global" -a "$global" != "-" ] || continue
                 if [ "$global" = "auto" ]; then
                         if [ "$addr" = "-" ]; then
@@ -15,6 +15,16 @@
                                     "$nic"
                         fi
                 fi
+                if [ "$mac"] = "vrrp" ]; then
+                    [ "$vrid" != "-" ] || \
+                        fail_fatal "Invalid configuration for %s mac cannot be 'vrrp' if no vrid specified!"
+
+                    # fallback to inet for vridfamily if not specified
+                    [ "$vridfamily" = "-" ] && vridfamily="inet"
+
+                    [ "$vridfamily" = "inet" -a "$vridfamily" = "inet6" ] || \
+                        fail_fatal "Invalid configuration for %s vrid_family needs to be either 'inet' or 'inet6'!"
+                fi
                 if dladm show-vnic -p -o LINK $nic >/dev/null 2>&1; then
                         # VNIC already exists
                         continue
@@ -23,6 +33,7 @@

                 opt=
                 [ "$mac" != "-" ] && opt+=" -m $mac"
+                [ "$vrid" != "-" ] && opt+=" -V $vrid -A $vridfamily"
                 [ "$vlan" != "-" -a "$vlan" != "0" ] && opt+=" -v $vlan"
                 if ! dladm create-vnic -l $global $opt $nic; then
                         fail_fatal "Could not create VNIC %s/%s" \

Full function below for easier reading:

function config_vnics {
        demand_vnics | while read nic global mac vlan addr vrid vridfamily; do
                [ -n "$global" -a "$global" != "-" ] || continue
                if [ "$global" = "auto" ]; then
                        if [ "$addr" = "-" ]; then
                                fail_fatal "%s %s" \
                                    "Cannot use 'auto' global NIC" \
                                    "without allowed-address."
                        fi
                        global="`route -n get "$addr" | nawk '
                            / interface:/ {print $2; exit}'`"
                        if [ -z "$global" ]; then
                                fail_fatal \
                                    "Could not determine global-nic for %s" \
                                    "$nic"
                        fi
                fi
                if [ "$mac"] = "vrrp" ]; then
                    [ "$vrid" != "-" ] || \
                        fail_fatal "Invalid configuration for %s mac cannot be 'vrrp' if no vrid specified!"

                    # fallback to inet for vridfamily if not specified
                    [ "$vridfamily" = "-" ] && vridfamily="inet"

                    [ "$vridfamily" = "inet" -a "$vridfamily" = "inet6" ] || \
                        fail_fatal "Invalid configuration for %s vrid_family needs to be either 'inet' or 'inet6'!"
                fi
                if dladm show-vnic -p -o LINK $nic >/dev/null 2>&1; then
                        # VNIC already exists
                        continue
                fi
                log "Creating VNIC $nic/$global (mac: $mac, vlan: $vlan)"

                opt=
                [ "$mac" != "-" ] && opt+=" -m $mac"
                [ "$vrid" != "-" ] && opt+=" -V $vrid -A $vridfamily"
                [ "$vlan" != "-" -a "$vlan" != "0" ] && opt+=" -v $vlan"
                if ! dladm create-vnic -l $global $opt $nic; then
                        fail_fatal "Could not create VNIC %s/%s" \
                            "$nic" "$global"
                fi

                if [ "$mac" = "-" ]; then
                        # Record the assigned MAC address in the zone config
                        mac=`dladm show-vnic -p -o MACADDRESS $nic`
                        [ -n "$mac" ] && zonecfg -z $ZONENAME \
                            "select net physical=$nic; " \
                            "set mac-addr=$mac; " \
                            "end; exit"
                fi
        done
}

This is just a rough untested idea on how I would like to implement it, there is no vrid and vridfamily parsing added higher up to the awk script yet.

  1. when mac=vrrp, validate we have a vrid or throw a fatal error
  2. ensure vridfamily is set to inet or inet6, fallback to inet if unset
  3. inject the -V and -A flags before the -v flag as per the command output (not mentioned in the man page??)
sjorge@saturn:/usr/lib/brand/shared$ dladm create-vnic 2>&1 | grep -B 2 -A 1 vrid
    create-vnic      [-t] -l <link> [-m <value> | auto |
                     {factory [-n <slot-id>]} | {random [-r <prefix>]} |
                     {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]
                     [-p <prop>=<value>[,...]] <vnic-link>

Does this approach look good? If so flash this out more (update the awk parsing and such) and give it a spin.

An alternative idea I had was just to be able to feed it a vrrp mac e.g. 0:0:5e:0:1:62 for inet and 0:0:5e:0:2:62 for inet6 and then parse those to extract the vrid and vrid family from them, this is doable because the VRRP mac follow the same format:
0:0:5e:0: prefix, 1 for IPv4 (inet) or 2 for IPv6 (inet6), XX is the vrid in hex, so it's certainly possible to parse the required info from this, but I feel this would make for a lot of complex parsing in ksh which I prefer to avoid, simply creating a vnic with one of those mac addresses is not sufficient to make vrrpadm create-router happy, I tried.

Edit: some more context, https://blackdot.be/2021/12/using-vrrp-inside-a-lipkg-zone-on-omnios/ manually creating the vnic first and just passing it in works as a workaround but I would prefer not to manually have to create any vnics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions