Skip to content

Commit

Permalink
lxd/network: Configure necessary ports for VLAN handling
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Bolton <[email protected]>
  • Loading branch information
boltmark committed Oct 3, 2024
1 parent 4011fde commit 498b0b0
Showing 1 changed file with 71 additions and 1 deletion.
72 changes: 71 additions & 1 deletion lxd/network/driver_ovn.go
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,52 @@ func (n *ovn) startUplinkPort() error {
return fmt.Errorf("Failed starting uplink port, network type %q unsupported as OVN uplink", uplinkNet.Type())
}

// configurePortsForVLAN configures the necessary ports to handle VLAN traffic between
// the uplink network and OVN.
func (n *ovn) configurePortsForVLAN(vlan string, update bool) error {
if vlan == "" || update && n.config["vlan"] == vlan {
return nil
}

uplinkNet, err := LoadByName(n.state, api.ProjectDefaultName, n.config["network"])
if err != nil {
return err
}

ovs := openvswitch.NewOVS()
vars := n.uplinkPortBridgeVars(uplinkNet)
uplinkHostName := GetHostDevice(uplinkNet.Config()["parent"], uplinkNet.Config()["vlan"])
portName := uplinkHostName

// If uplink is a native linux bridge, set the VID of the uplink end of the veth interface.
if uplinkNet.Type() == "bridge" || IsNativeBridge(uplinkHostName) {
portName = vars.ovsEnd

// If we are updating the VLAN ID, ensure we remove the old filter entry from the uplink end of the veth interface.
link := &ip.Link{Name: vars.uplinkEnd}
if update {
err = link.BridgeVLANDelete(n.Config()["vlan"], false)
if err != nil {
return fmt.Errorf("Failed to remove old VLAN filter entry for uplink veth interface %q: %w", vars.uplinkEnd, err)
}
}

// Add VLAN filter entry to the uplink end of the veth interface.
err = link.BridgeVLANAdd(vlan, false, false, false)
if err != nil {
return fmt.Errorf("Failed to configure VLAN for uplink veth interface %q: %w", vars.uplinkEnd, err)
}
}

// Configure vlan_mode and trunk on the OVS end of the veth interface.
err = ovs.BridgePortSet(portName, "vlan_mode=trunk", fmt.Sprintf("trunk=%s", vlan))
if err != nil {
return fmt.Errorf("Failed to configure VLAN for uplink veth interface %q on OVS bridge %q: %w", portName, vars.ovsBridge, err)
}

return err
}

// uplinkOperationLockName returns the lock name to use for operations on the uplink network.
func (n *ovn) uplinkOperationLockName(uplinkNet Network) string {
return fmt.Sprintf("network.ovn.%s", uplinkNet.Name())
Expand Down Expand Up @@ -2302,8 +2348,19 @@ func (n *ovn) setup(update bool) error {
return fmt.Errorf("Failed linking external router port to external switch port: %w", err)
}

// If VLAN is provided, ensure localnet port is properly tagged.
localnetOpts := &openvswitch.OVNSwitchPortOpts{}
if n.config["vlan"] != "" {
vlan, err := strconv.ParseUint(n.Config()["vlan"], 10, 16)
if err != nil {
return fmt.Errorf("Invalid VLAN ID %q: %w", n.Config()["vlan"], err)
}

localnetOpts.VLAN = uint16(vlan)
}

// Create external switch port and link to external provider network.
err = client.LogicalSwitchPortAdd(n.getExtSwitchName(), n.getExtSwitchProviderPortName(), nil, update)
err = client.LogicalSwitchPortAdd(n.getExtSwitchName(), n.getExtSwitchProviderPortName(), localnetOpts, update)
if err != nil {
return fmt.Errorf("Failed adding external switch provider port: %w", err)
}
Expand Down Expand Up @@ -3104,6 +3161,13 @@ func (n *ovn) Start() error {
return err
}

// If VLAN config is provided to the OVN network, configure the necessary ports
// to handle traffic on the specified VLAN.
err = n.configurePortsForVLAN(n.config["vlan"], false)
if err != nil {
return err
}

// Setup BGP.
err = n.bgpSetup(nil)
if err != nil {
Expand Down Expand Up @@ -3218,6 +3282,12 @@ func (n *ovn) Update(newNetwork api.NetworkPut, targetNode string, clientType re
delete(newNetwork.Config, ovnVolatileUplinkIPv6)
}

// Update port configurations for VLAN if necessary.
err = n.configurePortsForVLAN(newNetwork.Config["vlan"], true)
if err != nil {
return err
}

// Apply changes to all nodes and databse.
err = n.common.update(newNetwork, targetNode, clientType)
if err != nil {
Expand Down

0 comments on commit 498b0b0

Please sign in to comment.