f-28: bridge: first split bridge vxlan
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
9a16cf011a
commit
d457c73198
3 changed files with 153 additions and 57 deletions
|
|
@ -27,46 +27,48 @@ func CreateSubnet(db *badger.DB, subnetName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vxlanIface := fmt.Sprintf("vxlan-%d", d.vxlanID)
|
if err := createSubnet(db, subnetName, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := netif.CreateVethToNetns("v-"+d.subnetID+"-e", "v-"+d.subnetID+"-i", "/var/run/netns/"+d.vpc, 1500); err != nil {
|
return kv.AddInDB(db, "subnet/"+subnetName+"/state", "created")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSubnet(db *badger.DB, subnetName string, d subnetData) error {
|
||||||
|
vethE := "v-" + d.subnetID + "-e"
|
||||||
|
vethI := "v-" + d.subnetID + "-i"
|
||||||
|
|
||||||
|
if err := netif.CreateVethToNetns(vethE, vethI, "/var/run/netns/"+d.vpc, 1500); err != nil {
|
||||||
return fmt.Errorf("create veth: %w", err)
|
return fmt.Errorf("create veth: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch d.mode {
|
||||||
|
case "vxlan":
|
||||||
|
if err := setupVxlanHost(d, vethE); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "bridge":
|
||||||
|
if err := netif.BridgeSetMaster(vethE, d.localIface); err != nil {
|
||||||
|
return fmt.Errorf("add veth-e to bridge: %w", err)
|
||||||
|
}
|
||||||
|
if err := netif.LinkSetUp(vethE); err != nil {
|
||||||
|
return fmt.Errorf("set up %s: %w", vethE, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown subnet mode %q", d.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := netns.Call(d.vpc, func() error {
|
||||||
if err := netif.CreateBridge(d.bridge, 1500); err != nil {
|
if err := netif.CreateBridge(d.bridge, 1500); err != nil {
|
||||||
return fmt.Errorf("create bridge: %w", err)
|
return fmt.Errorf("create bridge: %w", err)
|
||||||
}
|
}
|
||||||
|
return netif.BridgeSetMaster(vethI, d.bridge)
|
||||||
if err := netns.Call(d.vpc, func() error {
|
|
||||||
return netif.CreateBridge(d.bridge, 1500)
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("create bridge in netns: %w", err)
|
return fmt.Errorf("setup bridge in netns: %w", err)
|
||||||
}
|
|
||||||
|
|
||||||
if err := netif.CreateVxlan(vxlanIface, d.vxlanID, d.localIface, 1500); err != nil {
|
|
||||||
return fmt.Errorf("create vxlan: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := netif.BridgeSetMaster("v-"+d.subnetID+"-e", d.bridge); err != nil {
|
|
||||||
return fmt.Errorf("add veth-e to bridge: %w", err)
|
|
||||||
}
|
|
||||||
if err := netns.Call(d.vpc, func() error {
|
|
||||||
return netif.BridgeSetMaster("v-"+d.subnetID+"-i", d.bridge)
|
|
||||||
}); err != nil {
|
|
||||||
return fmt.Errorf("add veth-i to bridge in netns: %w", err)
|
|
||||||
}
|
|
||||||
if err := netif.BridgeSetMaster(vxlanIface, d.bridge); err != nil {
|
|
||||||
return fmt.Errorf("add vxlan to bridge: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, iface := range []string{"v-" + d.subnetID + "-e", vxlanIface, d.bridge} {
|
|
||||||
if err := netif.LinkSetUp(iface); err != nil {
|
|
||||||
return fmt.Errorf("set up %s: %w", iface, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netns.Call(d.vpc, func() error {
|
if err := netns.Call(d.vpc, func() error {
|
||||||
for _, iface := range []string{"v-" + d.subnetID + "-i", d.bridge} {
|
for _, iface := range []string{vethI, d.bridge} {
|
||||||
if err := netif.LinkSetUp(iface); err != nil {
|
if err := netif.LinkSetUp(iface); err != nil {
|
||||||
return fmt.Errorf("set up %s: %w", iface, err)
|
return fmt.Errorf("set up %s: %w", iface, err)
|
||||||
}
|
}
|
||||||
|
|
@ -76,25 +78,65 @@ func CreateSubnet(db *badger.DB, subnetName string) error {
|
||||||
return fmt.Errorf("set up interfaces in netns: %w", err)
|
return fmt.Errorf("set up interfaces in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch d.mode {
|
||||||
|
case "vxlan":
|
||||||
if err := netns.Call(d.vpc, func() error {
|
if err := netns.Call(d.vpc, func() error {
|
||||||
return netif.AddrAdd(d.bridge, d.gatewayIP)
|
return netif.AddrAdd(d.bridge, d.gatewayIP)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("add addr to bridge in netns: %w", err)
|
return fmt.Errorf("add addr to bridge in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netns.Call(d.vpc, func() error {
|
if err := netns.Call(d.vpc, func() error {
|
||||||
return netif.RouteAdd(d.bridge, d.cidr)
|
return netif.RouteAdd(d.bridge, d.cidr)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("add route in netns: %w", err)
|
return fmt.Errorf("add route in netns: %w", err)
|
||||||
}
|
}
|
||||||
|
case "bridge":
|
||||||
|
}
|
||||||
|
|
||||||
|
applyEbtables := func() error {
|
||||||
if err := ebtables.DropARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
if err := ebtables.DropARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ebtables.DropDHCP(d.bridge); err != nil {
|
return ebtables.DropDHCP(d.bridge)
|
||||||
|
}
|
||||||
|
switch d.mode {
|
||||||
|
case "vxlan":
|
||||||
|
if err := applyEbtables(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "bridge":
|
||||||
|
if err := netns.Call(d.vpc, applyEbtables); err != nil {
|
||||||
|
return fmt.Errorf("set ebtables in netns: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return startDHCP(db, subnetName, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupVxlanHost(d subnetData, vethE string) error {
|
||||||
|
vxlanIface := fmt.Sprintf("vxlan-%d", d.vxlanID)
|
||||||
|
|
||||||
|
if err := netif.CreateBridge(d.bridge, 1500); err != nil {
|
||||||
|
return fmt.Errorf("create bridge: %w", err)
|
||||||
|
}
|
||||||
|
if err := netif.CreateVxlan(vxlanIface, d.vxlanID, d.localIface, 1500); err != nil {
|
||||||
|
return fmt.Errorf("create vxlan: %w", err)
|
||||||
|
}
|
||||||
|
if err := netif.BridgeSetMaster(vethE, d.bridge); err != nil {
|
||||||
|
return fmt.Errorf("add veth-e to bridge: %w", err)
|
||||||
|
}
|
||||||
|
if err := netif.BridgeSetMaster(vxlanIface, d.bridge); err != nil {
|
||||||
|
return fmt.Errorf("add vxlan to bridge: %w", err)
|
||||||
|
}
|
||||||
|
for _, iface := range []string{vethE, vxlanIface, d.bridge} {
|
||||||
|
if err := netif.LinkSetUp(iface); err != nil {
|
||||||
|
return fmt.Errorf("set up %s: %w", iface, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func startDHCP(db *badger.DB, subnetName string, d subnetData) error {
|
||||||
conf := dhcp.Config{
|
conf := dhcp.Config{
|
||||||
Network: d.cidr,
|
Network: d.cidr,
|
||||||
Gateway: d.gatewayIP,
|
Gateway: d.gatewayIP,
|
||||||
|
|
@ -118,6 +160,5 @@ func CreateSubnet(db *badger.DB, subnetName string) error {
|
||||||
if err := svc.Start("dnsmasq@" + conf.Name + ".service"); err != nil {
|
if err := svc.Start("dnsmasq@" + conf.Name + ".service"); err != nil {
|
||||||
return fmt.Errorf("start dnsmasq: %w", err)
|
return fmt.Errorf("start dnsmasq: %w", err)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
return kv.AddInDB(db, "subnet/"+subnetName+"/state", "created")
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ type subnetData struct {
|
||||||
vpc string
|
vpc string
|
||||||
subnetID string
|
subnetID string
|
||||||
bridge string
|
bridge string
|
||||||
|
mode string
|
||||||
vxlanID int
|
vxlanID int
|
||||||
localIface string
|
localIface string
|
||||||
gatewayIP net.IP
|
gatewayIP net.IP
|
||||||
|
|
@ -32,6 +33,13 @@ func loadSubnet(db *badger.DB, name string) (subnetData, error) {
|
||||||
}
|
}
|
||||||
d.vpc = vpc
|
d.vpc = vpc
|
||||||
|
|
||||||
|
mode, err := kv.GetFromDB(db, "subnet/"+name+"/mode")
|
||||||
|
if err != nil {
|
||||||
|
return d, fmt.Errorf("get mode: %w", err)
|
||||||
|
}
|
||||||
|
d.mode = mode
|
||||||
|
|
||||||
|
if d.mode == "vxlan" {
|
||||||
vxlanIDStr, err := kv.GetFromDB(db, "subnet/"+name+"/vxlan_id")
|
vxlanIDStr, err := kv.GetFromDB(db, "subnet/"+name+"/vxlan_id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return d, fmt.Errorf("get vxlan_id: %w", err)
|
return d, fmt.Errorf("get vxlan_id: %w", err)
|
||||||
|
|
@ -41,6 +49,7 @@ func loadSubnet(db *badger.DB, name string) (subnetData, error) {
|
||||||
return d, fmt.Errorf("parse vxlan_id: %w", err)
|
return d, fmt.Errorf("parse vxlan_id: %w", err)
|
||||||
}
|
}
|
||||||
d.vxlanID = vxlanID
|
d.vxlanID = vxlanID
|
||||||
|
}
|
||||||
|
|
||||||
localIface, err := kv.GetFromDB(db, "subnet/"+name+"/local_iface")
|
localIface, err := kv.GetFromDB(db, "subnet/"+name+"/local_iface")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,27 @@ func DeleteSubnet(db *badger.DB, subnetName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vxlanIface := fmt.Sprintf("vxlan-%d", d.vxlanID)
|
if err := stopDHCP(db, subnetName, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch d.mode {
|
||||||
|
case "vxlan":
|
||||||
|
if err := deleteSubnetVxlan(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "bridge":
|
||||||
|
if err := deleteSubnetBridge(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown subnet mode %q", d.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return kv.AddInDB(db, "subnet/"+subnetName+"/state", "deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopDHCP(db *badger.DB, subnetName string, d subnetData) error {
|
||||||
svc, err := systemd.New()
|
svc, err := systemd.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("connect to systemd: %w", err)
|
return fmt.Errorf("connect to systemd: %w", err)
|
||||||
|
|
@ -42,9 +61,15 @@ func DeleteSubnet(db *badger.DB, subnetName string) error {
|
||||||
if err := os.Remove("/etc/dnsmasq.d/" + d.vpc + "_" + d.bridge + ".conf"); err != nil && !os.IsNotExist(err) {
|
if err := os.Remove("/etc/dnsmasq.d/" + d.vpc + "_" + d.bridge + ".conf"); err != nil && !os.IsNotExist(err) {
|
||||||
return fmt.Errorf("remove dnsmasq config: %w", err)
|
return fmt.Errorf("remove dnsmasq config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := kv.DeleteInDB(db, "subnet/"+subnetName+"/dhcp"); err != nil {
|
if err := kv.DeleteInDB(db, "subnet/"+subnetName+"/dhcp"); err != nil {
|
||||||
return fmt.Errorf("delete dhcp entries: %w", err)
|
return fmt.Errorf("delete dhcp entries: %w", err)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteSubnetVxlan(d subnetData) error {
|
||||||
|
vxlanIface := fmt.Sprintf("vxlan-%d", d.vxlanID)
|
||||||
|
|
||||||
if err := ebtables.DeleteARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
if err := ebtables.DeleteARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
||||||
return fmt.Errorf("delete ebtables arp rule: %w", err)
|
return fmt.Errorf("delete ebtables arp rule: %w", err)
|
||||||
|
|
@ -70,6 +95,27 @@ func DeleteSubnet(db *badger.DB, subnetName string) error {
|
||||||
if err := netif.DeleteLink(d.bridge); err != nil {
|
if err := netif.DeleteLink(d.bridge); err != nil {
|
||||||
return fmt.Errorf("delete bridge: %w", err)
|
return fmt.Errorf("delete bridge: %w", err)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
return kv.AddInDB(db, "subnet/"+subnetName+"/state", "deleted")
|
}
|
||||||
|
|
||||||
|
func deleteSubnetBridge(d subnetData) error {
|
||||||
|
if err := netns.Call(d.vpc, func() error {
|
||||||
|
if err := ebtables.DeleteARPToGateway(d.bridge, d.gatewayIP.String()); err != nil {
|
||||||
|
return fmt.Errorf("delete ebtables arp rule: %w", err)
|
||||||
|
}
|
||||||
|
return ebtables.DeleteDHCP(d.bridge)
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("delete ebtables in netns: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := netns.Call(d.vpc, func() error {
|
||||||
|
return netif.DeleteLink(d.bridge)
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("delete bridge in netns: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := netif.DeleteLink("v-" + d.subnetID + "-e"); err != nil {
|
||||||
|
return fmt.Errorf("delete veth: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue