// setLinkOptions validates and sets link's various options passed in as LinkOptions. func setLinkOptions(ifc *net.Interface, opts LinkOptions) error { macaddr, mtu, flags, ns := opts.MacAddr, opts.MTU, opts.Flags, opts.Ns // if MTU is passed in LinkOptions if mtu != 0 { if err := validMtu(mtu); err != nil { return err } if err := netlink.NetworkSetMTU(ifc, mtu); err != nil { return fmt.Errorf("Unable to set MTU: %s", err) } } // if MacAddress is passed in LinkOptions if macaddr != "" { if err := validMacAddress(macaddr); err != nil { return err } if err := netlink.NetworkSetMacAddress(ifc, macaddr); err != nil { return fmt.Errorf("Unable to set MAC Address: %s", err) } } // if ns is passed in LinkOptions if ns != 0 { if err := validNs(ns); err != nil { return err } if err := netlink.NetworkSetNsPid(ifc, ns); err != nil { return fmt.Errorf("Unable to set Network namespace: %s", err) } } // if flags is passed in LinkOptions if flags != 0 { if err := validFlags(flags); err != nil { return err } if ns != 0 && (ns != 1 || ns != os.Getpid()) { if (flags & syscall.IFF_UP) == syscall.IFF_UP { origNs, _ := NetNsHandle(os.Getpid()) defer syscall.Close(int(origNs)) defer system.Setns(origNs, syscall.CLONE_NEWNET) if err := SetNetNsToPid(ns); err != nil { return fmt.Errorf("Switching to %d network namespace failed: %s", ns, err) } if err := netlink.NetworkLinkUp(ifc); err != nil { return fmt.Errorf("Unable to bring %s interface UP: %s", ifc.Name, ns) } } } else { if err := netlink.NetworkLinkUp(ifc); err != nil { return fmt.Errorf("Could not bring up network link %s: %s", ifc.Name, err) } } } return nil }
// NewVlanLinkWithOptions creates vlan network link and sets some of its network parameters // to values passed in as VlanOptions // // It is equivalent of running: // ip link add name ${vlan name} link ${master interface} address ${macaddress} type vlan id ${tag} // NewVlanLinkWithOptions returns Vlaner which is initialized to a pointer of type VlanLink if the // vlan link was created successfully on the Linux host. It accepts VlanOptions which allow you to set // link's options. It returns error if the link could not be created. func NewVlanLinkWithOptions(masterDev string, opts VlanOptions) (Vlaner, error) { id := opts.Id macaddr := opts.MacAddr if ok, err := NetInterfaceNameValid(masterDev); !ok { return nil, err } if _, err := net.InterfaceByName(masterDev); err != nil { return nil, fmt.Errorf("Master VLAN device %s does not exist on the host", masterDev) } vlanDev := opts.VlanDev if vlanDev != "" { if ok, err := NetInterfaceNameValid(vlanDev); !ok { return nil, err } if _, err := net.InterfaceByName(vlanDev); err == nil { return nil, fmt.Errorf("VLAN device %s already assigned on the host", vlanDev) } } else { return nil, fmt.Errorf("VLAN device name can not be empty!") } if id == 0 { return nil, fmt.Errorf("Incorrect VLAN tag specified: %d", id) } if err := netlink.NetworkLinkAddVlan(masterDev, vlanDev, id); err != nil { return nil, err } vlanIfc, err := net.InterfaceByName(vlanDev) if err != nil { return nil, fmt.Errorf("Could not find the new interface: %s", err) } if macaddr != "" { if _, err = net.ParseMAC(macaddr); err == nil { if err := netlink.NetworkSetMacAddress(vlanIfc, macaddr); err != nil { if errDel := DeleteLink(vlanIfc.Name); err != nil { return nil, fmt.Errorf("Incorrect options specified! Attempt to delete the link failed: %s", errDel) } } } } masterIfc, err := net.InterfaceByName(masterDev) if err != nil { return nil, fmt.Errorf("Could not find the new interface: %s", err) } return &VlanLink{ Link: Link{ ifc: vlanIfc, }, masterIfc: masterIfc, id: id, }, nil }
// SetLinkMacAddress sets link's MAC address. // It is equivalent of running: ip link set dev ${interface name} address ${address} func (l *Link) SetLinkMacAddress(macaddr string) error { return netlink.NetworkSetMacAddress(l.NetInterface(), macaddr) }
// NewMacVlanLinkWithOptions creates macvlan network link and sets som of its network parameters // passed in as MacVlanOptions. // // It is equivalent of running: // ip link add name ${macvlan name} link ${master interface} address ${macaddress} type macvlan mode ${mode} // NewMacVlanLinkWithOptions returns MacVlaner which is initialized to a pointer of type MacVlanLink if the // macvlan link was created successfully on the Linux host. It returns error if the macvlan link could not be created. func NewMacVlanLinkWithOptions(masterDev string, opts MacVlanOptions) (MacVlaner, error) { macVlanDev := opts.MacVlanDev mode := opts.Mode macaddr := opts.MacAddr if ok, err := NetInterfaceNameValid(masterDev); !ok { return nil, err } if _, err := net.InterfaceByName(masterDev); err != nil { return nil, fmt.Errorf("Master MAC VLAN device %s does not exist on the host", masterDev) } if macVlanDev != "" { if ok, err := NetInterfaceNameValid(macVlanDev); !ok { return nil, err } if _, err := net.InterfaceByName(macVlanDev); err == nil { return nil, fmt.Errorf("MAC VLAN device %s already assigned on the host", macVlanDev) } } else { macVlanDev = makeNetInterfaceName("mc") } if mode != "" { if _, ok := MacVlanModes[mode]; !ok { return nil, fmt.Errorf("Unsupported MacVlan mode specified: %s", mode) } } else { mode = "bridge" } if err := netlink.NetworkLinkAddMacVlan(masterDev, macVlanDev, opts.Mode); err != nil { return nil, err } macVlanIfc, err := net.InterfaceByName(macVlanDev) if err != nil { return nil, fmt.Errorf("Could not find the new interface: %s", err) } if macaddr != "" { if _, err = net.ParseMAC(macaddr); err == nil { if err := netlink.NetworkSetMacAddress(macVlanIfc, macaddr); err != nil { if errDel := DeleteLink(macVlanIfc.Name); err != nil { return nil, fmt.Errorf("Incorrect options specified. Attempt to delete the link failed: %s", errDel) } } } } masterIfc, err := net.InterfaceByName(masterDev) if err != nil { return nil, fmt.Errorf("Could not find the new interface: %s", err) } return &MacVlanLink{ Link: Link{ ifc: macVlanIfc, }, masterIfc: masterIfc, mode: mode, }, nil }