fix: vrf not clear

This commit is contained in:
Daniel Ding
2024-06-14 22:30:26 +08:00
parent e8d4cc09aa
commit 5220f9b14c
11 changed files with 308 additions and 811 deletions

View File

@@ -0,0 +1,32 @@
{
"name": "ipsec",
"provider": "ipsec",
"specifies": {
"tunnels": [
{
"remote": "3.3.2.1",
"secret": "d7ecd73ccc25",
"transport": "gre"
},
{
"remote": "3.3.2.2",
"secret": "d7ecd73ccc25",
"transport": "gre"
},
{
"localid": "@con1.ipsec.com",
"remote": "3.3.3.1",
"remoteport": "4501",
"secret": "d7ecd73ccc25",
"transport": "vxlan"
},
{
"localport": "4501",
"remote": "3.3.3.2",
"remoteid": "@con1.ipsec.com",
"secret": "d7ecd73ccc25",
"transport": "vxlan"
}
]
}
}

View File

@@ -1,16 +0,0 @@
{
"name": "v1024",
"provider": "vxlan",
"specifies": {
"vni": 1024,
"fabric": "fabric"
},
"bridge": {
"address": "192.168.55.1/24"
},
"subnet": {
"startAt": "192.168.55.100",
"endAt": "192.168.55.130"
},
"dhcp": "enable"
}

View File

@@ -14,3 +14,7 @@ set -ex
## Start pluto
/usr/libexec/ipsec/pluto --leak-detective --config /etc/ipsec.conf --nofork
## Clear xfrm
/sbin/ip xfrm policy flush
/sbin/ip xfrm state flush

View File

@@ -1,63 +0,0 @@
package config
type FabricSpecifies struct {
Mss int `json:"tcpMss,omitempty"`
Fragment bool `json:"fragment"`
Driver string `json:"driver,omitempty"`
Name string `json:"name,omitempty"`
Tunnels []*FabricTunnel `json:"tunnels"`
}
func (n *FabricSpecifies) Correct() {
for _, tun := range n.Tunnels {
tun.Correct()
if tun.DstPort == 0 {
if n.Driver == "stt" {
tun.DstPort = 7471
} else {
tun.DstPort = 4789 // 8472
}
}
}
}
func (n *FabricSpecifies) AddTunnel(obj *FabricTunnel) {
found := -1
for index, tun := range n.Tunnels {
if tun.Remote != obj.Remote {
continue
}
found = index
n.Tunnels[index] = obj
break
}
if found < 0 {
n.Tunnels = append(n.Tunnels, obj)
}
}
func (n *FabricSpecifies) DelTunnel(remote string) bool {
found := -1
for index, tun := range n.Tunnels {
if tun.Remote != remote {
continue
}
found = index
break
}
if found >= 0 {
copy(n.Tunnels[found:], n.Tunnels[found+1:])
n.Tunnels = n.Tunnels[:len(n.Tunnels)-1]
}
return found >= 0
}
type FabricTunnel struct {
DstPort uint32 `json:"destPort"`
Remote string `json:"remote"`
Local string `json:"local,omitempty"`
Mode string `json:"mode,omitempty"`
}
func (c *FabricTunnel) Correct() {
}

28
pkg/config/ipsec.go Normal file
View File

@@ -0,0 +1,28 @@
package config
type IPSecTunnel struct {
Left string `json:"local"`
LeftId string `json:"localid"`
LeftPort string `json:"localport"`
Right string `json:"remote"`
RightId string `json:"remoteid"`
RightPort string `json:"remoteport"`
Transport string `json:"transport"`
}
func (s *IPSecTunnel) Correct() {
if s.Left == "" {
s.Left = "%defaultroute"
}
}
type IPSecSpecifies struct {
Name string `json:"name"`
Tunnels []IPSecTunnel `json:"tunnels"`
}
func (s *IPSecSpecifies) Correct() {
for _, t := range s.Tunnels {
t.Correct()
}
}

View File

@@ -31,8 +31,8 @@ type Network struct {
func (n *Network) NewSpecifies() interface{} {
switch n.Provider {
case "vxlan":
n.Specifies = &VxLANSpecifies{}
case "ipsec":
n.Specifies = &IPSecSpecifies{}
case "router":
n.Specifies = &RouterSpecifies{}
default:
@@ -55,6 +55,12 @@ func (n *Network) Correct(sw *Switch) {
obj.Correct()
obj.Name = n.Name
}
case "ipsec":
spec := n.Specifies
if obj, ok := spec.(*IPSecSpecifies); ok {
obj.Correct()
obj.Name = n.Name
}
}
if n.Subnet == nil {
n.Subnet = &Subnet{}

View File

@@ -1,6 +0,0 @@
// +build !linux
package models
func (l *EspState) Update() {
}

View File

@@ -1,510 +0,0 @@
package cswitch
import (
"fmt"
"strings"
"github.com/danieldin95/go-openvswitch/ovs"
"github.com/luscis/openlan/pkg/api"
co "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol"
cn "github.com/luscis/openlan/pkg/network"
nl "github.com/vishvananda/netlink"
)
type Fabricer interface {
AddNetwork(cfg *co.Network)
DelNetwork(bridge string, vni uint32)
TcpMss() int
}
var fabrics = make(map[string]Fabricer)
func GetFabricer(name string) Fabricer {
return fabrics[name]
}
type OvsBridge struct {
name string
cli *ovs.Client
out *libol.SubLogger
}
func NewOvsBridge(name string) *OvsBridge {
return &OvsBridge{
name: name,
cli: ovs.New(),
out: libol.NewSubLogger(name),
}
}
func (o *OvsBridge) delFlow(flow *ovs.MatchFlow) error {
if err := o.cli.OpenFlow.DelFlows(o.name, flow); err != nil {
o.out.Warn("OvsBridge.addFlow %s", err)
return err
}
return nil
}
func (o *OvsBridge) addFlow(flow *ovs.Flow) error {
if err := o.cli.OpenFlow.AddFlow(o.name, flow); err != nil {
o.out.Warn("OvsBridge.addFlow %s", err)
return err
}
return nil
}
func (o *OvsBridge) setDown() error {
if err := o.cli.VSwitch.DeleteBridge(o.name); err != nil {
o.out.Error("OvsBridge.DeleteBridge %s %s", o.name, err)
return err
}
return nil
}
func (o *OvsBridge) setUp() error {
if err := o.cli.VSwitch.AddBridge(o.name); err != nil {
o.out.Error("OvsBridge.AddBridge %s %s", o.name, err)
return err
}
return nil
}
func (o *OvsBridge) setMode(mode ovs.FailMode) error {
if err := o.cli.VSwitch.SetFailMode(o.name, mode); err != nil {
o.out.Warn("OvsBridge.setMode %s %s", mode, err)
return err
}
return nil
}
func (o *OvsBridge) addPort(name string, options *ovs.InterfaceOptions) error {
if err := o.cli.VSwitch.AddPort(o.name, name); err != nil {
o.out.Warn("OvsBridge.addPort %s %s", name, err)
return err
}
if options == nil {
return nil
}
if err := o.cli.VSwitch.Set.Interface(name, *options); err != nil {
o.out.Warn("OvsBridge.addPort %s %s", name, err)
return err
}
return nil
}
func (o *OvsBridge) delPort(name string) error {
if err := o.cli.VSwitch.DeletePort(o.name, name); err != nil {
o.out.Warn("OvsBridge.delPort %s %s", name, err)
return err
}
return nil
}
func (o *OvsBridge) setPort(name string, options ovs.InterfaceOptions) error {
if err := o.cli.VSwitch.Set.Interface(name, options); err != nil {
o.out.Warn("OvsBridge.setPort %s %s", name, err)
return err
}
return nil
}
func (o *OvsBridge) dumpPort(name string) *ovs.PortStats {
if port, err := o.cli.OpenFlow.DumpPort(o.name, name); err != nil {
o.out.Warn("OvsBridge.dumpPort %s %s", name, err)
return nil
} else {
return port
}
}
const (
TLsToTun = 2 // From a switch include border to tunnels.
TTunToLs = 4 // From tunnels to a switch.
TSourceLearn = 10 // Learning source mac.
TUcastToTun = 20 // Forwarding by fdb.
TFloodToTun = 30 // Flooding to tunnels or patch by flags.
TFloodToBor = 31 // Flooding to border in a switch.
TFloodLoop = 32 // Flooding to patch in a switch from border.
)
const (
FFromLs = 2 // In a logical switch.
FFromTun = 4 // From peer tunnels.
)
const (
MatchRegFlag = "reg10"
NxmRegFlag = "NXM_NX_REG10[0..31]"
NxmRegEthDst = "NXM_OF_ETH_DST[]"
NxmRegEthSrc = "NXM_OF_ETH_SRC[]"
NxmRegTunId = "NXM_NX_TUN_ID[0..31]"
NxmRegInPort = "NXM_OF_IN_PORT[]"
)
type OvsPort struct {
name string
portId int
options ovs.InterfaceOptions
}
type FabricWorker struct {
*WorkerImpl
spec *co.FabricSpecifies
ovs *OvsBridge
cookie uint64
tunnels map[string]*OvsPort
borders map[string]*OvsPort
bridge map[string]*cn.LinuxBridge
}
func NewFabricWorker(c *co.Network) *FabricWorker {
w := &FabricWorker{
WorkerImpl: NewWorkerApi(c),
ovs: NewOvsBridge(c.Bridge.Name),
tunnels: make(map[string]*OvsPort, 1024),
borders: make(map[string]*OvsPort, 1024),
bridge: make(map[string]*cn.LinuxBridge, 1024),
}
w.spec, _ = c.Specifies.(*co.FabricSpecifies)
fabrics[c.Name] = w
return w
}
func (w *FabricWorker) upTables() {
_ = w.ovs.addFlow(&ovs.Flow{
Actions: []ovs.Action{ovs.Drop()},
})
// Table 2: set flags from logical switch.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TLsToTun,
Priority: 1,
Actions: []ovs.Action{
ovs.Load(libol.Uint2S(FFromLs), NxmRegFlag),
ovs.Resubmit(0, TSourceLearn),
},
})
// Table 4: set flags from tunnels.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TTunToLs,
Priority: 1,
Actions: []ovs.Action{
ovs.Load(libol.Uint2S(FFromTun), NxmRegFlag),
ovs.Resubmit(0, TSourceLearn),
},
})
// Table 10: source learning
w.addLearning()
// Table 20: default to flood 30
_ = w.ovs.addFlow(&ovs.Flow{
Table: TUcastToTun,
Actions: []ovs.Action{
ovs.Resubmit(0, TFloodToTun),
},
})
// Table 30: default drop.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodToTun,
Actions: []ovs.Action{ovs.Drop()},
})
// Table 31: default drop.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodToBor,
Actions: []ovs.Action{ovs.Drop()},
})
}
func (w *FabricWorker) Initialize() {
w.WorkerImpl.Initialize()
if err := w.ovs.setUp(); err != nil {
return
}
_ = w.ovs.setMode("secure")
w.upTables()
api.ListWorker(func(n api.Networker) {
if w.IsSlave(n) {
n.Initialize()
}
})
}
func (w *FabricWorker) vni2peer(vni uint32) (string, string) {
tunPort := fmt.Sprintf("vb-%08d", vni)
brPort := fmt.Sprintf("vt-%08d", vni)
return brPort, tunPort
}
func (w *FabricWorker) UpLink(bridge string, vni uint32, addr string) *ovs.PortStats {
brPort, tunPort := w.vni2peer(vni)
link := &nl.Veth{
LinkAttrs: nl.LinkAttrs{Name: tunPort},
PeerName: brPort,
}
if err := nl.LinkAdd(link); err != nil {
w.out.Warn("FabricWorker.addLink %s", err)
}
if err := nl.LinkSetUp(link); err != nil {
w.out.Warn("FabricWorker.setLinkUp %s", err)
}
// Setup linux bridge for outputs
br := cn.NewLinuxBridge(bridge, 0)
br.Open(addr)
_ = br.AddSlave(brPort)
if err := br.CallIptables(1); err != nil {
w.out.Warn("FabricWorker.IpTables %s", err)
}
w.bridge[bridge] = br
// Add port to OvS tunnel bridge
_ = w.ovs.addPort(tunPort, nil)
if port := w.ovs.dumpPort(tunPort); port != nil {
return port
}
return nil
}
func (w *FabricWorker) addLearning() {
// Table 10: source mac learning
learnSpecs := []ovs.Match{
ovs.FieldMatch(NxmRegTunId, NxmRegTunId),
ovs.FieldMatch(NxmRegEthDst, NxmRegEthSrc),
}
learnActions := []ovs.Action{
ovs.OutputField(NxmRegInPort),
}
_ = w.ovs.addFlow(&ovs.Flow{
Table: TSourceLearn,
Actions: []ovs.Action{
ovs.Learn(&ovs.LearnedFlow{
Table: TUcastToTun,
Matches: learnSpecs,
Priority: 1,
HardTimeout: 300,
Actions: learnActions,
}),
ovs.Resubmit(0, TUcastToTun),
},
})
}
func (w *FabricWorker) AddNetwork(cfg *co.Network) {
spec, _ := cfg.Specifies.(*co.VxLANSpecifies)
libol.Info("Fabric.AddNetwork %d", spec.Vni)
patch := w.UpLink(cfg.Bridge.Name, spec.Vni, cfg.Bridge.Address)
// Table 0: load tunnel id from patch port.
_ = w.ovs.addFlow(&ovs.Flow{
InPort: patch.PortID,
Priority: 1,
Actions: []ovs.Action{
ovs.Load(libol.Uint2S(spec.Vni), NxmRegTunId),
ovs.Resubmit(0, TLsToTun),
},
})
// Table 30: flooding to patch from tunnels.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodToTun,
Priority: 2,
Matches: []ovs.Match{
ovs.FieldMatch(NxmRegTunId, libol.Uint2S(spec.Vni)),
ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromTun)),
},
Actions: []ovs.Action{
ovs.Output(patch.PortID),
ovs.Resubmit(0, TFloodToBor),
},
})
// Table 32: flooding to patch from border.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodLoop,
Priority: 2,
Matches: []ovs.Match{
ovs.FieldMatch(NxmRegTunId, libol.Uint2S(spec.Vni)),
ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromLs)),
},
Actions: []ovs.Action{
ovs.Output(patch.PortID),
},
})
}
func (w *FabricWorker) Addr2Port(addr, pre string) string {
name := pre + strings.ReplaceAll(addr, ".", "")
return libol.IfName(name)
}
func (w *FabricWorker) flood2Tunnel() {
var actions []ovs.Action
for _, tun := range w.tunnels {
actions = append(actions, ovs.Output(tun.portId))
}
actions = append(actions, ovs.Resubmit(0, TFloodToBor))
// Table 30: Flooding to tunnels from patch.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodToTun,
Priority: 1,
Matches: []ovs.Match{
ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromLs)),
},
Actions: actions,
})
}
func (w *FabricWorker) flood2Border() {
var actions []ovs.Action
for _, port := range w.borders {
actions = append(actions, ovs.Output(port.portId))
}
// Table 31: flooding to border from tunnels.
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodToBor,
Priority: 1,
Matches: []ovs.Match{
ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromTun)),
},
Actions: actions,
})
// Table 32: flooding to border from a border.
actions = append(actions, ovs.Resubmit(0, TFloodLoop))
_ = w.ovs.addFlow(&ovs.Flow{
Table: TFloodToBor,
Priority: 1,
Matches: []ovs.Match{
ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromLs)),
},
Actions: actions,
})
}
func (w *FabricWorker) tunnelType() ovs.InterfaceType {
if w.spec.Driver == "stt" {
return ovs.InterfaceTypeSTT
}
return ovs.InterfaceTypeVXLAN
}
func (w *FabricWorker) AddTunnel(cfg co.FabricTunnel) {
name := w.Addr2Port(cfg.Remote, "vx-")
options := ovs.InterfaceOptions{
Type: w.tunnelType(),
BfdEnable: true,
RemoteIP: cfg.Remote,
Key: "flow",
DstPort: cfg.DstPort,
}
if w.spec.Fragment {
options.DfDefault = "false"
} else {
options.DfDefault = "true"
}
if err := w.ovs.addPort(name, &options); err != nil {
return
}
port := w.ovs.dumpPort(name)
if port == nil {
return
}
if cfg.Mode == "border" {
_ = w.ovs.addFlow(&ovs.Flow{
InPort: port.PortID,
Priority: 1,
Actions: []ovs.Action{
ovs.Resubmit(0, TLsToTun),
},
})
w.borders[name] = &OvsPort{
name: name,
portId: port.PortID,
options: options,
}
// Update flow for flooding to border.
w.flood2Border()
} else {
_ = w.ovs.addFlow(&ovs.Flow{
InPort: port.PortID,
Priority: 1,
Actions: []ovs.Action{
ovs.Resubmit(0, TTunToLs),
},
})
w.tunnels[name] = &OvsPort{
name: name,
portId: port.PortID,
options: options,
}
// Update flow for flooding to tunnels.
w.flood2Tunnel()
}
}
func (w *FabricWorker) Start(v api.Switcher) {
w.out.Info("FabricWorker.Start")
for _, tunnel := range w.spec.Tunnels {
w.AddTunnel(*tunnel)
}
w.WorkerImpl.Start(v)
api.ListWorker(func(n api.Networker) {
if w.IsSlave(n) {
n.Start(v)
}
})
}
func (w *FabricWorker) downTables() {
_ = w.ovs.delFlow(nil)
}
func (w *FabricWorker) DelNetwork(bridge string, vni uint32) {
brPort, tunPort := w.vni2peer(vni)
if err := w.ovs.delPort(tunPort); err != nil {
libol.Warn("FabricWorker.downNetwork %s", err)
}
link := &nl.Veth{
LinkAttrs: nl.LinkAttrs{Name: tunPort},
PeerName: brPort,
}
_ = nl.LinkDel(link)
if br, ok := w.bridge[bridge]; ok {
_ = br.Close()
}
}
func (w *FabricWorker) DelTunnel(name string) {
_ = w.ovs.delPort(name)
}
func (w *FabricWorker) IsSlave(n api.Networker) bool {
cfg := n.Config()
if cfg == nil || cfg.Specifies == nil {
return false
}
spec, ok := cfg.Specifies.(*co.VxLANSpecifies)
if !ok || spec.Fabric != w.cfg.Name {
return false
}
return true
}
func (w *FabricWorker) Stop() {
w.out.Info("FabricWorker.Stop")
api.ListWorker(func(n api.Networker) {
if w.IsSlave(n) {
n.Stop()
}
})
w.WorkerImpl.Stop()
w.downTables()
for _, tunnel := range w.tunnels {
w.DelTunnel(tunnel.name)
}
}
func (w *FabricWorker) Reload(v api.Switcher) {
w.Stop()
w.Initialize()
w.Start(v)
}
func (w *FabricWorker) TcpMss() int {
return w.cfg.Bridge.Mss
}

230
pkg/switch/ipsec.go Normal file
View File

@@ -0,0 +1,230 @@
package cswitch
import (
"fmt"
"os"
"text/template"
"github.com/luscis/openlan/pkg/api"
co "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol"
)
type IPSecWorker struct {
*WorkerImpl
spec *co.IPSecSpecifies
}
func NewIPSecWorker(c *co.Network) *IPSecWorker {
w := &IPSecWorker{
WorkerImpl: NewWorkerApi(c),
}
w.spec, _ = c.Specifies.(*co.IPSecSpecifies)
return w
}
// conn vxlan11252
// keyexchange=ike
// ikev2=no
// type=transport
// left=%defaultroute
// right=45.135.117.235
// rightikeport=4501
// authby=secret
// conn vxlan11252-c2
// auto=start
// also=vxlan11252
// leftid=@c2.vxlan11252.com
// leftprotoport=udp/8472
// rightprotoport=udp
// conn vxlan11252-c1
// auto=start
// also=vxlan11252
// leftid=@c1.vxlan11252.com
// leftprotoport=udp
// rightprotoport=udp/8472
// conn vxlan11252
// keyexchange=ike
// ikev2=no
// type=transport
// left=%defaultroute
// leftikeport=4501
// right=218.94.118.90
// authby=secret
// conn vxlan11252-c1
// auto=start
// also=vxlan11252
// rightid=@c1.vxlan11252.com
// leftprotoport=udp/8472
// rightprotoport=udp
// conn vxlan11252-c2
// auto=start
// also=vxlan11252
// rightid=@c2.vxlan11252.com
// leftprotoport=udp
// rightprotoport=udp/8472
const (
vxlanTmpl = `
conn {{ .Name }}
keyexchange=ike
ikev2=no
type=transport
left={{ .Left }}
{{- if .LeftId }}
leftid={{ .LeftId }}
{{- end }}
{{- if .LeftPort }}
leftikeport={{ .LeftPort }}
{{- end }}
right={{ .Right }}
{{- if .RightId }}
rightid={{ .RightId }}
{{- end }}
{{- if .RightPort }}
rightikeport={{ .RightPort }}
{{- end }}
authby=secret
conn {{ .Name }}-c1
auto=start
also={{ .Name }}
leftprotoport=udp/8472
rightprotoport=udp
conn {{ .Name }}-c2
auto=start
also={{ .Remote }}-{{ .Protocol }}
leftprotoport=udp
rightprotoport=udp/8472
`
greTmpl = `
conn {{ .Name }}-c1
auto=start
ikev2=insist
type=transport
left={{ .Left }}
right={{ .Right }}
authby=secret
leftprotoport=gre
rightprotoport=gre
`
secretTmpl = `
%any {{ .Remote }} : PSK "{{ .Secret }}"
`
)
func (w *IPSecWorker) Initialize() {
w.out.Info("IPSecWorker.Initialize")
}
func (w *IPSecWorker) saveSec(name, tmpl string, data interface{}) error {
file := fmt.Sprintf("/etc/ipsec.d/%s", name)
out, err := libol.CreateFile(file)
if err != nil || out == nil {
return err
}
defer out.Close()
if obj, err := template.New("main").Parse(tmpl); err != nil {
return err
} else {
if err := obj.Execute(out, data); err != nil {
return err
}
}
return nil
}
func (w *IPSecWorker) startConn(name string) {
promise := libol.NewPromise()
promise.Go(func() error {
if out, err := libol.Exec("ipsec", "auto", "--start", "--asynchronous", name); err != nil {
w.out.Warn("IPSecWorker.startConn: %v %s", out, err)
return err
}
w.out.Info("IPSecWorker.startConn: %v success", name)
return nil
})
}
func (w *IPSecWorker) AddTunnel(tunnel *co.IPSecTunnel) error {
connTmpl := ""
secTmpl := ""
name := fmt.Sprintf("%s-%s", tunnel.Right, tunnel.Transport)
if tunnel.Transport == "vxlan" {
connTmpl = vxlanTmpl
secTmpl = secretTmpl
} else if tunnel.Transport == "gre" {
connTmpl = greTmpl
secTmpl = secretTmpl
}
if secTmpl != "" {
if err := w.saveSec(name+".secrets", secTmpl, tunnel); err != nil {
w.out.Error("WorkerImpl.AddTunnel %s", err)
return err
}
libol.Exec("ipsec", "auto", "--rereadsecrets")
}
if connTmpl != "" {
if err := w.saveSec(name+".conf", connTmpl, tunnel); err != nil {
w.out.Error("WorkerImpl.AddTunnel %s", err)
return err
}
if tunnel.Transport == "vxlan" {
w.startConn(name + "-c1")
w.startConn(name + "-c2")
} else if tunnel.Transport == "gre" {
w.startConn(name + "-c1")
}
}
return nil
}
func (w *IPSecWorker) Start(v api.Switcher) {
w.uuid = v.UUID()
w.out.Info("IPSecWorker.Start")
}
func (w *IPSecWorker) RemoveTunnel(tunnel *co.IPSecTunnel) error {
name := fmt.Sprintf("%s-%s", tunnel.Right, tunnel.Transport)
if tunnel.Transport == "vxlan" {
libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-c1")
libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-c2")
} else if tunnel.Transport == "gre" {
libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-c1")
}
cfile := fmt.Sprintf("/etc/ipsec.d/%s.conf", name)
sfile := fmt.Sprintf("/etc/ipsec.d/%s.secrets", name)
if err := libol.FileExist(cfile); err == nil {
if err := os.Remove(cfile); err != nil {
w.out.Warn("IPSecWorker.RemoveTunnel %s", err)
}
}
if err := libol.FileExist(sfile); err == nil {
if err := os.Remove(sfile); err != nil {
w.out.Warn("IPSecWorker.RemoveTunnel %s", err)
}
}
return nil
}
func (w *IPSecWorker) Stop() {
w.out.Info("IPSecWorker.Stop")
}
func (w *IPSecWorker) Reload(v api.Switcher) {
w.Stop()
w.Initialize()
w.Start(v)
}

View File

@@ -3,9 +3,7 @@ package cswitch
import (
"fmt"
"net"
"os"
"strings"
"text/template"
"time"
"github.com/luscis/openlan/pkg/api"
@@ -21,8 +19,8 @@ import (
func NewNetworker(c *co.Network) api.Networker {
var obj api.Networker
switch c.Provider {
case "vxlan":
obj = NewVxLANWorker(c)
case "ipsec":
obj = NewIPSecWorker(c)
case "router":
obj = NewRouterWorker(c)
default:
@@ -185,12 +183,6 @@ func (w *WorkerImpl) AddPhysical(bridge string, output string) {
}
func (w *WorkerImpl) addOutput(bridge string, port *LinuxPort) {
if port.output.Secret != "" {
if err := w.addSecConn(port); err != nil {
w.out.Error("WorkerImpl.addOutput %s", err)
}
}
cfg := port.output
mtu := 0
if cfg.Protocol == "gre" {
@@ -469,12 +461,6 @@ func (w *WorkerImpl) DelPhysical(bridge string, output string) {
}
func (w *WorkerImpl) delOutput(bridge string, port *LinuxPort) {
if port.output.Secret != "" {
if err := w.delSecConn(port); err != nil {
w.out.Error("WorkerImpl.AddOutput %s", err)
}
}
cfg := port.output
w.out.Info("WorkerImpl.delOutput %s %s", port.link, port.String())
@@ -558,11 +544,9 @@ func (w *WorkerImpl) Stop() {
w.out.Info("WorkerImpl.Stop")
w.fire.Stop()
w.nextgroup.Stop()
w.unloadRoutes()
if !(w.vpn == nil) {
if !(w.ztrust == nil) {
w.ztrust.Stop()
@@ -570,14 +554,14 @@ func (w *WorkerImpl) Stop() {
if !(w.qos == nil) {
w.qos.Stop()
}
w.vpn.Stop()
}
if !(w.dhcp == nil) {
w.dhcp.Stop()
}
if !(w.vrf == nil) {
w.vrf.Down()
}
for _, output := range w.outputs {
w.delOutput(w.cfg.Bridge.Name, output)
@@ -588,7 +572,6 @@ func (w *WorkerImpl) Stop() {
w.setR.Destroy()
w.setV.Destroy()
}
func (w *WorkerImpl) String() string {
@@ -1080,119 +1063,6 @@ func (w *WorkerImpl) ACLer() api.ACLer {
return w.acl
}
const (
vxlanConn = `
conn vxlan{{ .Segment }}-in
keyingtries=%forever
auto=start
ike=aes_gcm256-sha2_256
esp=aes_gcm256
ikev2=insist
type=transport
left=%defaultroute
right={{ .Remote }}
authby=secret
leftprotoport=udp/8472
rightprotoport=udp
conn vxlan{{ .Segment }}-out
keyingtries=%forever
auto=start
ike=aes_gcm256-sha2_256
esp=aes_gcm256
ikev2=insist
type=transport
left=%defaultroute
right={{ .Remote }}
authby=secret
leftprotoport=udp
rightprotoport=udp/8472
`
greConn = `
conn gre{{ .Segment }}
keyingtries=%forever
auto=start
ike=aes_gcm256-sha2_256
esp=aes_gcm256
ikev2=insist
type=transport
left=%defaultroute
right={{ .Remote }}
authby=secret
leftprotoport=gre
rightprotoport=gre
`
secretConn = `
%any {{ .Remote }} : PSK "{{ .Secret }}"
`
)
func (w *WorkerImpl) saveSec(name, tmpl string, data interface{}) error {
file := fmt.Sprintf("/etc/ipsec.d/%s", name)
out, err := libol.CreateFile(file)
if err != nil || out == nil {
return err
}
defer out.Close()
if obj, err := template.New("main").Parse(tmpl); err != nil {
return err
} else {
if err := obj.Execute(out, data); err != nil {
return err
}
}
return nil
}
func (w *WorkerImpl) startSecConn(name string) {
promise := libol.NewPromise()
promise.Go(func() error {
if out, err := libol.Exec("ipsec", "auto", "--start", "--asynchronous", name); err != nil {
w.out.Warn("WorkerImpl.startSecConn: %v %s", out, err)
return err
}
w.out.Info("WorkerImpl.startSecConn: %v success", name)
return nil
})
}
func (w *WorkerImpl) addSecConn(port *LinuxPort) error {
connTmpl := ""
secTmpl := ""
name := port.link
data := port.output
if data.Protocol == "vxlan" {
connTmpl = vxlanConn
secTmpl = secretConn
} else if data.Protocol == "gre" {
connTmpl = vxlanConn
secTmpl = secretConn
}
if secTmpl != "" {
if err := w.saveSec(name+".secrets", secTmpl, data); err != nil {
w.out.Error("WorkerImpl.addSecConn %s", err)
return err
}
libol.Exec("ipsec", "auto", "--rereadsecrets")
}
if connTmpl != "" {
if err := w.saveSec(name+".conf", connTmpl, data); err != nil {
w.out.Error("WorkerImpl.addSecConn %s", err)
return err
}
if data.Protocol == "vxlan" {
w.startSecConn(name + "-in")
w.startSecConn(name + "-out")
} else if data.Protocol == "gre" {
w.startSecConn(name)
}
}
return nil
}
func (w *WorkerImpl) AddOutput(data schema.Output) {
output := co.Output{
Segment: data.Segment,
@@ -1210,33 +1080,6 @@ func (w *WorkerImpl) AddOutput(data schema.Output) {
w.outputs = append(w.outputs, port)
}
func (w *WorkerImpl) delSecConn(port *LinuxPort) error {
data := port.output
name := port.link
if data.Protocol == "vxlan" {
libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-in")
libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-out")
} else if data.Protocol == "gre" {
libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name)
}
cfile := fmt.Sprintf("/etc/ipsec.d/%s.conf", name)
sfile := fmt.Sprintf("/etc/ipsec.d/%s.secrets", name)
if err := libol.FileExist(cfile); err == nil {
if err := os.Remove(cfile); err != nil {
w.out.Warn("WorkerImpl.delSecConn %s", err)
}
}
if err := libol.FileExist(sfile); err == nil {
if err := os.Remove(sfile); err != nil {
w.out.Warn("WorkerImpl.delSecConn %s", err)
}
}
return nil
}
func (w *WorkerImpl) DelOutput(device string) {
var port *LinuxPort
for _, v := range w.outputs {

View File

@@ -1,51 +0,0 @@
package cswitch
import (
"github.com/luscis/openlan/pkg/api"
co "github.com/luscis/openlan/pkg/config"
)
type VxLANWorker struct {
*WorkerImpl
spec *co.VxLANSpecifies
}
func NewVxLANWorker(c *co.Network) *VxLANWorker {
w := &VxLANWorker{
WorkerImpl: NewWorkerApi(c),
}
w.spec, _ = c.Specifies.(*co.VxLANSpecifies)
return w
}
func (w *VxLANWorker) Initialize() {
w.WorkerImpl.Initialize()
}
func (w *VxLANWorker) Start(v api.Switcher) {
w.uuid = v.UUID()
master := GetFabricer(w.spec.Fabric)
if master == nil {
w.out.Warn("VxLANWorker.Start %s not found", w.spec.Fabric)
return
}
w.cfg.Bridge.Mss = master.TcpMss()
master.AddNetwork(w.cfg)
w.WorkerImpl.Start(v)
}
func (w *VxLANWorker) Stop() {
w.WorkerImpl.Stop()
master := GetFabricer(w.spec.Fabric)
if master == nil {
w.out.Warn("VxLANWorker.Stop %s not found", w.spec.Fabric)
return
}
master.DelNetwork(w.cfg.Bridge.Name, w.spec.Vni)
}
func (w *VxLANWorker) Reload(v api.Switcher) {
w.Stop()
w.Initialize()
w.Start(v)
}