fix: vxlan support openvpn

This commit is contained in:
Daniel Ding
2024-01-06 00:21:52 +08:00
parent 842b32a549
commit 8159e73256
5 changed files with 192 additions and 269 deletions

View File

@@ -50,7 +50,7 @@ networks:
# docker exec -it powerdns_auth_1 bash # docker exec -it powerdns_auth_1 bash
## ZONE ## ZONE
# pdnsutil create-zone luscis.io # pdnsutil create-zone luscis.io
# pdnsutil add-record luscis.io @ NS admin.ns.luscis.io # pdnsutil add-record luscis.io @ NS ns1.luscis.io
## A ## A
# pdnsutil add-record luscis.io a0 A 192.168.0.88 # pdnsutil add-record luscis.io a0 A 192.168.0.88
@@ -58,13 +58,13 @@ networks:
## A ## A
# pdnsutil create-zone jump.io # pdnsutil create-zone jump.io
# pdnsutil add-record jump.io @ NS admin.ns.jump.io # pdnsutil add-record jump.io @ NS ns1.jump.io
# pdnsutil add-record jump.io a86 A 192.168.0.86 # pdnsutil add-record jump.io a86 A 192.168.0.86
## PTR ## PTR
# pdnsutil create-zone 168.192.in-addr.arpa # pdnsutil create-zone 168.192.in-addr.arpa
# pdnsutil add-record 168.192.in-addr.arpa 84.0 PTR a0.luscis.io # pdnsutil add-record 168.192.in-addr.arpa 84.0 PTR a0.luscis.io
# pdnsutil add-record 168.192.in-addr.arpa @ NS admin.ns.168.192.in-addr.arpa # pdnsutil add-record 168.192.in-addr.arpa @ NS ns1.168.192.in-addr.arpa
# pdnsutil list-zone 168.192.in-addr.arpa # pdnsutil list-zone 168.192.in-addr.arpa

View File

@@ -50,6 +50,7 @@ type Networker interface {
Reload(v Switcher) Reload(v Switcher)
Provider() string Provider() string
ZTruster() ZTruster ZTruster() ZTruster
IfAddr() string
} }
var workers = make(map[string]Networker) var workers = make(map[string]Networker)

View File

@@ -5,12 +5,16 @@ import (
"net" "net"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/luscis/openlan/pkg/api" "github.com/luscis/openlan/pkg/api"
"github.com/luscis/openlan/pkg/cache"
co "github.com/luscis/openlan/pkg/config" co "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol" "github.com/luscis/openlan/pkg/libol"
"github.com/luscis/openlan/pkg/models"
cn "github.com/luscis/openlan/pkg/network" cn "github.com/luscis/openlan/pkg/network"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
nl "github.com/vishvananda/netlink"
) )
func NewNetworker(c *co.Network) api.Networker { func NewNetworker(c *co.Network) api.Networker {
@@ -64,6 +68,34 @@ func (w *WorkerImpl) Provider() string {
} }
func (w *WorkerImpl) Initialize() { func (w *WorkerImpl) Initialize() {
n := models.Network{
Name: w.cfg.Name,
IpStart: w.cfg.Subnet.Start,
IpEnd: w.cfg.Subnet.End,
Netmask: w.cfg.Subnet.Netmask,
IfAddr: w.cfg.Bridge.Address,
Routes: make([]*models.Route, 0, 2),
}
for _, rt := range w.cfg.Routes {
if rt.NextHop == "" {
w.out.Warn("WorkerImpl.Initialize: %s noNextHop", rt.Prefix)
continue
}
rte := models.NewRoute(rt.Prefix, w.IfAddr(), rt.Mode)
if rt.Metric > 0 {
rte.Metric = rt.Metric
}
if rt.NextHop != "" {
rte.Origin = rt.NextHop
}
n.Routes = append(n.Routes, rte)
}
cache.Network.Add(&n)
w.updateVPN()
w.createVPN()
if w.cfg.Dhcp == "enable" { if w.cfg.Dhcp == "enable" {
w.dhcp = NewDhcp(&co.Dhcp{ w.dhcp = NewDhcp(&co.Dhcp{
Name: w.cfg.Name, Name: w.cfg.Name,
@@ -71,18 +103,23 @@ func (w *WorkerImpl) Initialize() {
Bridge: w.cfg.Bridge, Bridge: w.cfg.Bridge,
}) })
} }
w.fire = cn.NewFireWallTable(w.cfg.Name) w.fire = cn.NewFireWallTable(w.cfg.Name)
if out, err := w.setV.Clear(); err != nil { if out, err := w.setV.Clear(); err != nil {
w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err) w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err)
} }
if out, err := w.setR.Clear(); err != nil { if out, err := w.setR.Clear(); err != nil {
w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err) w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err)
} }
w.newVPN()
if w.cfg.ZTrust == "enable" { if w.cfg.ZTrust == "enable" {
w.ztrust = NewZTrust(w.cfg.Name, 30) w.ztrust = NewZTrust(w.cfg.Name, 30)
w.ztrust.Initialize() w.ztrust.Initialize()
} }
w.forwardSubnet()
w.forwardVPN()
} }
func (w *WorkerImpl) AddPhysical(bridge string, vlan int, output string) { func (w *WorkerImpl) AddPhysical(bridge string, vlan int, output string) {
@@ -167,21 +204,70 @@ func (w *WorkerImpl) AddOutput(bridge string, port *LinuxPort) {
w.AddPhysical(bridge, port.vlan, port.link) w.AddPhysical(bridge, port.vlan, port.link)
} }
func (w *WorkerImpl) loadRoutes() {
// install routes
cfg := w.cfg
w.out.Debug("WorkerImpl.LoadRoute: %v", cfg.Routes)
ifAddr := w.IfAddr()
for _, rt := range cfg.Routes {
_, dst, err := net.ParseCIDR(rt.Prefix)
if err != nil {
continue
}
if ifAddr == rt.NextHop && rt.MultiPath == nil {
// route's next-hop is local not install again.
continue
}
nlrt := nl.Route{Dst: dst}
for _, hop := range rt.MultiPath {
nxhe := &nl.NexthopInfo{
Hops: hop.Weight,
Gw: net.ParseIP(hop.NextHop),
}
nlrt.MultiPath = append(nlrt.MultiPath, nxhe)
}
if rt.MultiPath == nil {
nlrt.Gw = net.ParseIP(rt.NextHop)
nlrt.Priority = rt.Metric
}
w.out.Debug("WorkerImpl.LoadRoute: %s", nlrt.String())
promise := &libol.Promise{
First: time.Second * 2,
MaxInt: time.Minute,
MinInt: time.Second * 10,
}
rt_c := rt
promise.Go(func() error {
if err := nl.RouteReplace(&nlrt); err != nil {
w.out.Warn("WorkerImpl.LoadRoute: %v %s", nlrt, err)
return err
}
w.out.Info("WorkerImpl.LoadRoute: %v success", rt_c.String())
return nil
})
}
}
func (w *WorkerImpl) Start(v api.Switcher) { func (w *WorkerImpl) Start(v api.Switcher) {
cfg, vpn := w.GetCfgs() cfg, vpn := w.GetCfgs()
fire := w.fire fire := w.fire
w.out.Info("WorkerImpl.Start") w.out.Info("WorkerImpl.Start")
w.loadRoutes()
if cfg.Acl != "" { if cfg.Acl != "" {
fire.Mangle.Pre.AddRule(cn.IpRule{ fire.Mangle.Pre.AddRule(cn.IpRule{
Input: cfg.Bridge.Name, Input: cfg.Bridge.Name,
Jump: cfg.Acl, Jump: cfg.Acl,
}) })
} }
fire.Filter.For.AddRule(cn.IpRule{ fire.Filter.For.AddRule(cn.IpRule{
Input: cfg.Bridge.Name, Input: cfg.Bridge.Name,
Output: cfg.Bridge.Name, Output: cfg.Bridge.Name,
}) })
if cfg.Bridge.Mss > 0 { if cfg.Bridge.Mss > 0 {
// forward to remote // forward to remote
fire.Mangle.Post.AddRule(cn.IpRule{ fire.Mangle.Post.AddRule(cn.IpRule{
@@ -202,6 +288,7 @@ func (w *WorkerImpl) Start(v api.Switcher) {
SetMss: cfg.Bridge.Mss, SetMss: cfg.Bridge.Mss,
}) })
} }
for _, output := range cfg.Outputs { for _, output := range cfg.Outputs {
port := &LinuxPort{ port := &LinuxPort{
name: output.Interface, name: output.Interface,
@@ -210,6 +297,7 @@ func (w *WorkerImpl) Start(v api.Switcher) {
w.AddOutput(cfg.Bridge.Name, port) w.AddOutput(cfg.Bridge.Name, port)
w.outputs = append(w.outputs, port) w.outputs = append(w.outputs, port)
} }
if !(w.dhcp == nil) { if !(w.dhcp == nil) {
w.dhcp.Start() w.dhcp.Start()
fire.Nat.Post.AddRule(cn.IpRule{ fire.Nat.Post.AddRule(cn.IpRule{
@@ -219,6 +307,7 @@ func (w *WorkerImpl) Start(v api.Switcher) {
Comment: "Default Gateway for DHCP", Comment: "Default Gateway for DHCP",
}) })
} }
if !(w.vpn == nil) { if !(w.vpn == nil) {
w.vpn.Start() w.vpn.Start()
} }
@@ -236,6 +325,7 @@ func (w *WorkerImpl) Start(v api.Switcher) {
Comment: "Goto Zero Trust", Comment: "Goto Zero Trust",
}) })
} }
fire.Start() fire.Start()
} }
@@ -285,24 +375,53 @@ func (w *WorkerImpl) DelOutput(bridge string, port *LinuxPort) {
} }
} }
func (w *WorkerImpl) unloadRoutes() {
cfg := w.cfg
for _, rt := range cfg.Routes {
_, dst, err := net.ParseCIDR(rt.Prefix)
if err != nil {
continue
}
nlRt := nl.Route{Dst: dst}
if rt.MultiPath == nil {
nlRt.Gw = net.ParseIP(rt.NextHop)
nlRt.Priority = rt.Metric
}
w.out.Debug("WorkerImpl.UnLoadRoute: %s", nlRt.String())
if err := nl.RouteDel(&nlRt); err != nil {
w.out.Warn("WorkerImpl.UnLoadRoute: %s", err)
continue
}
w.out.Info("WorkerImpl.UnLoadRoute: %v", rt.String())
}
}
func (w *WorkerImpl) Stop() { func (w *WorkerImpl) Stop() {
w.out.Info("WorkerImpl.Stop") w.out.Info("WorkerImpl.Stop")
w.fire.Stop() w.fire.Stop()
if !(w.vpn == nil || w.ztrust == nil) { if !(w.vpn == nil || w.ztrust == nil) {
w.ztrust.Stop() w.ztrust.Stop()
} }
if !(w.vpn == nil) { if !(w.vpn == nil) {
w.vpn.Stop() w.vpn.Stop()
} }
if !(w.dhcp == nil) { if !(w.dhcp == nil) {
w.dhcp.Stop() w.dhcp.Stop()
} }
for _, output := range w.outputs { for _, output := range w.outputs {
w.DelOutput(w.cfg.Bridge.Name, output) w.DelOutput(w.cfg.Bridge.Name, output)
} }
w.outputs = nil w.outputs = nil
w.setR.Destroy() w.setR.Destroy()
w.setV.Destroy() w.setV.Destroy()
w.unloadRoutes()
} }
func (w *WorkerImpl) String() string { func (w *WorkerImpl) String() string {
@@ -322,6 +441,27 @@ func (w *WorkerImpl) Config() *co.Network {
} }
func (w *WorkerImpl) Subnet() string { func (w *WorkerImpl) Subnet() string {
cfg := w.cfg
ipAddr := cfg.Bridge.Address
ipMask := cfg.Subnet.Netmask
if ipAddr == "" {
ipAddr = cfg.Subnet.Start
}
if ipAddr == "" {
return ""
}
addr := ipAddr
if ipMask != "" {
prefix := libol.Netmask2Len(ipMask)
ifAddr := strings.SplitN(ipAddr, "/", 2)[0]
addr = fmt.Sprintf("%s/%d", ifAddr, prefix)
}
if _, inet, err := net.ParseCIDR(addr); err == nil {
return inet.String()
}
return "" return ""
} }
@@ -411,12 +551,19 @@ func (w *WorkerImpl) GetCfgs() (*co.Network, *co.OpenVPN) {
return cfg, vpn return cfg, vpn
} }
func (w *WorkerImpl) updateVPN(routes []string) { func (w *WorkerImpl) updateVPN() {
cfg, vpn := w.GetCfgs() cfg, vpn := w.GetCfgs()
if cfg == nil { if vpn == nil {
return return
} }
routes := vpn.Routes
routes = append(routes, vpn.Subnet) // add subnet of VPN self.
if addr := w.Subnet(); addr != "" {
w.out.Info("WorkerImpl.updateVPN subnet %s", addr)
routes = append(routes, addr)
}
for _, rt := range cfg.Routes { for _, rt := range cfg.Routes {
addr := rt.Prefix addr := rt.Prefix
if addr == "0.0.0.0/0" { if addr == "0.0.0.0/0" {
@@ -460,7 +607,36 @@ func (w *WorkerImpl) forwardVPN() {
w.toMasq_r(vpn.Subnet, w.setV.Name, "From VPN") w.toMasq_r(vpn.Subnet, w.setV.Name, "From VPN")
} }
func (w *WorkerImpl) newVPN() { func (w *WorkerImpl) forwardSubnet() {
cfg, vpn := w.GetCfgs()
br := cfg.Bridge
ifAddr := strings.SplitN(br.Address, "/", 2)[0]
if ifAddr == "" {
return
}
subnet := w.Subnet()
// Enable MASQUERADE, and FORWARD it.
w.toRelated(br.Name, "Accept related")
for _, rt := range cfg.Routes {
if rt.MultiPath != nil {
continue
}
if rt.Prefix == "0.0.0.0/0" {
w.setR.Add("0.0.0.0/1")
w.setR.Add("128.0.0.0/1")
break
}
w.setR.Add(rt.Prefix)
}
w.toForward_r(br.Name, subnet, w.setR.Name, "To route")
if vpn != nil {
w.toMasq_s(w.setR.Name, vpn.Subnet, "To VPN")
}
w.toMasq_r(subnet, w.setR.Name, "To Masq")
}
func (w *WorkerImpl) createVPN() {
_, vpn := w.GetCfgs() _, vpn := w.GetCfgs()
if vpn == nil { if vpn == nil {
return return
@@ -474,3 +650,7 @@ func (w *WorkerImpl) newVPN() {
func (w *WorkerImpl) ZTruster() api.ZTruster { func (w *WorkerImpl) ZTruster() api.ZTruster {
return w.ztrust return w.ztrust
} }
func (w *WorkerImpl) IfAddr() string {
return strings.SplitN(w.cfg.Bridge.Address, "/", 2)[0]
}

View File

@@ -1,16 +1,12 @@
package cswitch package cswitch
import ( import (
"fmt"
"net"
"strings"
"time" "time"
"github.com/luscis/openlan/pkg/api" "github.com/luscis/openlan/pkg/api"
"github.com/luscis/openlan/pkg/cache" "github.com/luscis/openlan/pkg/cache"
co "github.com/luscis/openlan/pkg/config" co "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol" "github.com/luscis/openlan/pkg/libol"
"github.com/luscis/openlan/pkg/models"
cn "github.com/luscis/openlan/pkg/network" cn "github.com/luscis/openlan/pkg/network"
nl "github.com/vishvananda/netlink" nl "github.com/vishvananda/netlink"
) )
@@ -38,91 +34,21 @@ func NewOpenLANWorker(c *co.Network) *OpenLANWorker {
} }
} }
func (w *OpenLANWorker) updateVPN() {
_, vpn := w.GetCfgs()
if vpn == nil {
return
}
routes := vpn.Routes
routes = append(routes, vpn.Subnet)
if addr := w.Subnet(); addr != "" {
w.out.Info("OpenLANWorker.updateVPN subnet %s", addr)
routes = append(routes, addr)
}
w.WorkerImpl.updateVPN(routes)
}
func (w *OpenLANWorker) forwardSubnet() {
cfg, vpn := w.GetCfgs()
br := cfg.Bridge
ifAddr := strings.SplitN(br.Address, "/", 2)[0]
if ifAddr == "" {
return
}
subnet := w.Subnet()
// Enable MASQUERADE, and FORWARD it.
w.toRelated(br.Name, "Accept related")
for _, rt := range cfg.Routes {
if rt.MultiPath != nil {
continue
}
if rt.Prefix == "0.0.0.0/0" {
w.setR.Add("0.0.0.0/1")
w.setR.Add("128.0.0.0/1")
break
}
w.setR.Add(rt.Prefix)
}
w.toForward_r(br.Name, subnet, w.setR.Name, "To route")
if vpn != nil {
w.toMasq_s(w.setR.Name, vpn.Subnet, "To VPN")
}
w.toMasq_r(subnet, w.setR.Name, "To Masq")
}
func (w *OpenLANWorker) Initialize() { func (w *OpenLANWorker) Initialize() {
brCfg := w.cfg.Bridge brCfg := w.cfg.Bridge
n := models.Network{ name := w.cfg.Name
Name: w.cfg.Name,
IpStart: w.cfg.Subnet.Start,
IpEnd: w.cfg.Subnet.End,
Netmask: w.cfg.Subnet.Netmask,
IfAddr: w.cfg.Bridge.Address,
Routes: make([]*models.Route, 0, 2),
}
for _, rt := range w.cfg.Routes {
if rt.NextHop == "" {
w.out.Warn("OpenLANWorker.Initialize: %s noNextHop", rt.Prefix)
continue
}
rte := models.NewRoute(rt.Prefix, w.IfAddr(), rt.Mode)
if rt.Metric > 0 {
rte.Metric = rt.Metric
}
if rt.NextHop != "" {
rte.Origin = rt.NextHop
}
n.Routes = append(n.Routes, rte)
}
cache.Network.Add(&n)
for _, ht := range w.cfg.Hosts { for _, ht := range w.cfg.Hosts {
lease := cache.Network.AddLease(ht.Hostname, ht.Address, n.Name) lease := cache.Network.AddLease(ht.Hostname, ht.Address, name)
if lease != nil { if lease != nil {
lease.Type = "static" lease.Type = "static"
lease.Network = w.cfg.Name lease.Network = name
} }
} }
w.bridge = cn.NewBridger(brCfg.Provider, brCfg.Name, brCfg.IPMtu) w.bridge = cn.NewBridger(brCfg.Provider, brCfg.Name, brCfg.IPMtu)
w.updateVPN()
w.WorkerImpl.Initialize() w.WorkerImpl.Initialize()
w.forwardSubnet()
w.forwardVPN()
} }
func (w *OpenLANWorker) LoadLinks() { func (w *OpenLANWorker) LoadLinks() {
@@ -142,71 +68,6 @@ func (w *OpenLANWorker) UnLoadLinks() {
} }
} }
func (w *OpenLANWorker) LoadRoutes() {
// install routes
cfg := w.cfg
w.out.Debug("OpenLANWorker.LoadRoute: %v", cfg.Routes)
ifAddr := w.IfAddr()
for _, rt := range cfg.Routes {
_, dst, err := net.ParseCIDR(rt.Prefix)
if err != nil {
continue
}
if ifAddr == rt.NextHop && rt.MultiPath == nil {
// route's next-hop is local not install again.
continue
}
nlrt := nl.Route{Dst: dst}
for _, hop := range rt.MultiPath {
nxhe := &nl.NexthopInfo{
Hops: hop.Weight,
Gw: net.ParseIP(hop.NextHop),
}
nlrt.MultiPath = append(nlrt.MultiPath, nxhe)
}
if rt.MultiPath == nil {
nlrt.Gw = net.ParseIP(rt.NextHop)
nlrt.Priority = rt.Metric
}
w.out.Debug("OpenLANWorker.LoadRoute: %s", nlrt.String())
promise := &libol.Promise{
First: time.Second * 2,
MaxInt: time.Minute,
MinInt: time.Second * 10,
}
rt_c := rt
promise.Go(func() error {
if err := nl.RouteReplace(&nlrt); err != nil {
w.out.Warn("OpenLANWorker.LoadRoute: %v %s", nlrt, err)
return err
}
w.out.Info("OpenLANWorker.LoadRoute: %v success", rt_c.String())
return nil
})
}
}
func (w *OpenLANWorker) UnLoadRoutes() {
cfg := w.cfg
for _, rt := range cfg.Routes {
_, dst, err := net.ParseCIDR(rt.Prefix)
if err != nil {
continue
}
nlRt := nl.Route{Dst: dst}
if rt.MultiPath == nil {
nlRt.Gw = net.ParseIP(rt.NextHop)
nlRt.Priority = rt.Metric
}
w.out.Debug("OpenLANWorker.UnLoadRoute: %s", nlRt.String())
if err := nl.RouteDel(&nlRt); err != nil {
w.out.Warn("OpenLANWorker.UnLoadRoute: %s", err)
continue
}
w.out.Info("OpenLANWorker.UnLoadRoute: %v", rt.String())
}
}
func (w *OpenLANWorker) UpBridge(cfg *co.Bridge) { func (w *OpenLANWorker) UpBridge(cfg *co.Bridge) {
master := w.bridge master := w.bridge
// new it and configure address // new it and configure address
@@ -276,7 +137,6 @@ func (w *OpenLANWorker) Start(v api.Switcher) {
w.out.Info("OpenLANWorker.Start") w.out.Info("OpenLANWorker.Start")
w.UpBridge(w.cfg.Bridge) w.UpBridge(w.cfg.Bridge)
w.LoadLinks() w.LoadLinks()
w.LoadRoutes()
w.WorkerImpl.Start(v) w.WorkerImpl.Start(v)
} }
@@ -304,7 +164,6 @@ func (w *OpenLANWorker) closePeer(cfg *co.Bridge) {
func (w *OpenLANWorker) Stop() { func (w *OpenLANWorker) Stop() {
w.out.Info("OpenLANWorker.Close") w.out.Info("OpenLANWorker.Close")
w.WorkerImpl.Stop() w.WorkerImpl.Stop()
w.UnLoadRoutes()
w.UnLoadLinks() w.UnLoadLinks()
w.startTime = 0 w.startTime = 0
w.downBridge(w.cfg.Bridge) w.downBridge(w.cfg.Bridge)
@@ -343,36 +202,10 @@ func (w *OpenLANWorker) DelLink(addr string) {
} }
} }
func (w *OpenLANWorker) Subnet() string {
cfg := w.cfg
ipAddr := cfg.Bridge.Address
ipMask := cfg.Subnet.Netmask
if ipAddr == "" {
ipAddr = cfg.Subnet.Start
}
if ipAddr != "" {
addr := ipAddr
if ipMask != "" {
prefix := libol.Netmask2Len(ipMask)
ifAddr := strings.SplitN(ipAddr, "/", 2)[0]
addr = fmt.Sprintf("%s/%d", ifAddr, prefix)
}
if _, inet, err := net.ParseCIDR(addr); err == nil {
return inet.String()
}
}
return ""
}
func (w *OpenLANWorker) Bridge() cn.Bridger { func (w *OpenLANWorker) Bridge() cn.Bridger {
return w.bridge return w.bridge
} }
func (w *OpenLANWorker) IfAddr() string {
return strings.SplitN(w.cfg.Bridge.Address, "/", 2)[0]
}
func (w *OpenLANWorker) Reload(v api.Switcher) { func (w *OpenLANWorker) Reload(v api.Switcher) {
w.Stop() w.Stop()
w.Initialize() w.Initialize()

View File

@@ -1,13 +1,8 @@
package cswitch package cswitch
import ( import (
"net"
"time"
"github.com/luscis/openlan/pkg/api" "github.com/luscis/openlan/pkg/api"
co "github.com/luscis/openlan/pkg/config" co "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol"
nl "github.com/vishvananda/netlink"
) )
type RouterWorker struct { type RouterWorker struct {
@@ -23,93 +18,9 @@ func NewRouterWorker(c *co.Network) *RouterWorker {
return w return w
} }
func (w *RouterWorker) updateVPN() {
spec := w.spec
_, vpn := w.GetCfgs()
if vpn == nil {
return
}
routes := vpn.Routes
routes = append(routes, vpn.Subnet)
for _, sub := range spec.Subnets {
w.out.Info("RouterWorker.updateVPN subnet %s", sub.CIDR)
routes = append(routes, sub.CIDR)
}
w.WorkerImpl.updateVPN(routes)
}
func (w *RouterWorker) Initialize() { func (w *RouterWorker) Initialize() {
w.updateVPN()
w.WorkerImpl.Initialize() w.WorkerImpl.Initialize()
w.Forward() w.Forward()
w.forwardVPN()
}
func (w *RouterWorker) LoadRoutes() {
// install routes
cfg := w.cfg
w.out.Debug("RouterWorker.LoadRoute: %v", cfg.Routes)
for _, rt := range cfg.Routes {
_, dst, err := net.ParseCIDR(rt.Prefix)
if err != nil {
continue
}
if rt.NextHop == "" && rt.MultiPath == nil {
// route's next-hop is local not install again.
continue
}
nlrt := nl.Route{Dst: dst}
for _, hop := range rt.MultiPath {
nxhe := &nl.NexthopInfo{
Hops: hop.Weight,
Gw: net.ParseIP(hop.NextHop),
}
nlrt.MultiPath = append(nlrt.MultiPath, nxhe)
}
if rt.MultiPath == nil {
nlrt.Gw = net.ParseIP(rt.NextHop)
nlrt.Priority = rt.Metric
}
w.out.Debug("RouterWorker.LoadRoute: %s", nlrt.String())
promise := &libol.Promise{
First: time.Second * 2,
MaxInt: time.Minute,
MinInt: time.Second * 10,
}
rt_c := rt
promise.Go(func() error {
if err := nl.RouteReplace(&nlrt); err != nil {
w.out.Warn("RouterWorker.LoadRoute: %v %s", nlrt, err)
return err
}
w.out.Info("RouterWorker.LoadRoute: %v success", rt_c.String())
return nil
})
}
}
func (w *RouterWorker) UnLoadRoutes() {
cfg := w.cfg
for _, rt := range cfg.Routes {
_, dst, err := net.ParseCIDR(rt.Prefix)
if err != nil {
continue
}
nlRt := nl.Route{Dst: dst}
if rt.MultiPath == nil {
nlRt.Gw = net.ParseIP(rt.NextHop)
nlRt.Priority = rt.Metric
}
w.out.Debug("RouterWorker.UnLoadRoute: %s", nlRt.String())
if err := nl.RouteDel(&nlRt); err != nil {
w.out.Warn("RouterWorker.UnLoadRoute: %s", err)
continue
}
w.out.Info("RouterWorker.UnLoadRoute: %v", rt.String())
}
} }
func (w *RouterWorker) Forward() { func (w *RouterWorker) Forward() {
@@ -129,13 +40,11 @@ func (w *RouterWorker) Forward() {
func (w *RouterWorker) Start(v api.Switcher) { func (w *RouterWorker) Start(v api.Switcher) {
w.uuid = v.UUID() w.uuid = v.UUID()
w.LoadRoutes()
w.WorkerImpl.Start(v) w.WorkerImpl.Start(v)
} }
func (w *RouterWorker) Stop() { func (w *RouterWorker) Stop() {
w.WorkerImpl.Stop() w.WorkerImpl.Stop()
w.UnLoadRoutes()
} }
func (w *RouterWorker) Reload(v api.Switcher) { func (w *RouterWorker) Reload(v api.Switcher) {