Created
January 25, 2016 23:56
-
-
Save abhi/c1cad7dd58f0de1eba80 to your computer and use it in GitHub Desktop.
Netplugin: L3 integration with BGP for containers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/core/core.go b/core/core.go | |
old mode 100644 | |
new mode 100755 | |
index 01ec78d..3a60187 | |
--- a/core/core.go | |
+++ b/core/core.go | |
@@ -79,6 +79,8 @@ type InstanceInfo struct { | |
HostLabel string `json:"host-label"` | |
VtepIP string `json:"vtep-ip"` | |
VlanIntf string `json:"vlan-if"` | |
+ RouterIP string `json:"router-ip"` | |
+ FwdMode string `json:"fwd-mode"` | |
} | |
// Driver implements the programming logic | |
@@ -90,13 +92,15 @@ type NetworkDriver interface { | |
Init(config *Config, info *InstanceInfo) error | |
Deinit() | |
CreateNetwork(id string) error | |
- DeleteNetwork(id, encap string, pktTag, extPktTag int) error | |
+ DeleteNetwork(id, encap string, pktTag, extPktTag int, gateway string) error | |
CreateEndpoint(id string) error | |
DeleteEndpoint(id string) error | |
AddPeerHost(node ServiceInfo) error | |
DeletePeerHost(node ServiceInfo) error | |
AddMaster(node ServiceInfo) error | |
DeleteMaster(node ServiceInfo) error | |
+ AddBgpNeighbors(id string) error | |
+ DeleteBgpNeighbors(id string) error | |
} | |
// WatchState is used to provide a difference between core.State structs by | |
diff --git a/drivers/fakenetepdriver.go b/drivers/fakenetepdriver.go | |
old mode 100644 | |
new mode 100755 | |
index 1858e38..cb26c96 | |
--- a/drivers/fakenetepdriver.go | |
+++ b/drivers/fakenetepdriver.go | |
@@ -26,7 +26,7 @@ func (d *FakeNetEpDriver) CreateNetwork(id string) error { | |
} | |
// DeleteNetwork is not implemented. | |
-func (d *FakeNetEpDriver) DeleteNetwork(id, encap string, pktTag, extPktTag int) error { | |
+func (d *FakeNetEpDriver) DeleteNetwork(id, encap string, pktTag, extPktTag int, gateway string) error { | |
return core.Errorf("Not implemented") | |
} | |
@@ -59,3 +59,13 @@ func (d *FakeNetEpDriver) AddMaster(node core.ServiceInfo) error { | |
func (d *FakeNetEpDriver) DeleteMaster(node core.ServiceInfo) error { | |
return core.Errorf("Not implemented") | |
} | |
+ | |
+// AddBgpNeighbors is not implemented. | |
+func (d *FakeNetEpDriver) AddBgpNeighbors(id string) (err error) { | |
+ return core.Errorf("Not implemented") | |
+} | |
+ | |
+// DeleteBgpNeighbors is not implemented. | |
+func (d *FakeNetEpDriver) DeleteBgpNeighbors(id string) (err error) { | |
+ return core.Errorf("Not implemented") | |
+} | |
diff --git a/drivers/ovsSwitch.go b/drivers/ovsSwitch.go | |
old mode 100644 | |
new mode 100755 | |
index 98e5435..90fe94f | |
--- a/drivers/ovsSwitch.go | |
+++ b/drivers/ovsSwitch.go | |
@@ -16,6 +16,7 @@ limitations under the License. | |
package drivers | |
import ( | |
+ "errors" | |
"fmt" | |
"net" | |
"strings" | |
@@ -42,30 +43,31 @@ type OvsSwitch struct { | |
} | |
// NewOvsSwitch Creates a new OVS switch instance | |
-func NewOvsSwitch(bridgeName, netType, localIP string) (*OvsSwitch, error) { | |
+func NewOvsSwitch(bridgeName, netType, localIP string, fwdMode string, routerInfo ...string) (*OvsSwitch, error) { | |
var err error | |
sw := new(OvsSwitch) | |
sw.bridgeName = bridgeName | |
sw.netType = netType | |
- // Determine the failure mode | |
- failMode := "" | |
- if netType == "vxlan" { | |
- failMode = "secure" | |
- } | |
- | |
- // Create OVS db driver | |
- sw.ovsdbDriver, err = NewOvsdbDriver(bridgeName, failMode) | |
- if err != nil { | |
- log.Fatalf("Error creating ovsdb driver. Err: %v", err) | |
- } | |
- | |
// For Vxlan, initialize ofnet. For VLAN mode, we use OVS normal forwarding | |
if netType == "vxlan" { | |
+ // Create OVS db driver | |
+ sw.ovsdbDriver, err = NewOvsdbDriver(bridgeName, "secure") | |
+ if err != nil { | |
+ log.Fatalf("Error creating ovsdb driver. Err: %v", err) | |
+ } | |
// Create an ofnet agent | |
- sw.ofnetAgent, err = ofnet.NewOfnetAgent("vxlan", net.ParseIP(localIP), | |
- ofnet.OFNET_AGENT_PORT, 6633) | |
+ if fwdMode == "bridge" { | |
+ sw.ofnetAgent, err = ofnet.NewOfnetAgent("vxlan", net.ParseIP(localIP), | |
+ ofnet.OFNET_AGENT_VXLAN_PORT, 6633) | |
+ } else if fwdMode == "routing" { | |
+ sw.ofnetAgent, err = ofnet.NewOfnetAgent("vrouter", net.ParseIP(localIP), | |
+ ofnet.OFNET_AGENT_VXLAN_PORT, 6633) | |
+ } else { | |
+ log.Errorf("Invalid Forwarding mode") | |
+ return nil, errors.New("Invalid forwarding mode. Expects 'bridge' or 'routing'") | |
+ } | |
if err != nil { | |
log.Fatalf("Error initializing ofnet") | |
return nil, err | |
@@ -91,6 +93,54 @@ func NewOvsSwitch(bridgeName, netType, localIP string) (*OvsSwitch, error) { | |
log.Infof("Switch (vxlan) connected.") | |
} | |
+ if netType == "vlan" { | |
+ // Create an ofnet agent | |
+ if fwdMode == "bridge" { | |
+ //For vlan bridge fwd mode ofnetAgent is not instantiated | |
+ // Create OVS db driver | |
+ sw.ovsdbDriver, err = NewOvsdbDriver(bridgeName, "") | |
+ if err != nil { | |
+ log.Fatalf("Error creating ovsdb driver. Err: %v", err) | |
+ } | |
+ return sw, nil | |
+ } else if fwdMode == "routing" { | |
+ // Create OVS db driver | |
+ sw.ovsdbDriver, err = NewOvsdbDriver(bridgeName, "secure") | |
+ if err != nil { | |
+ log.Fatalf("Error creating ovsdb driver. Err: %v", err) | |
+ } | |
+ sw.ofnetAgent, err = ofnet.NewOfnetAgent("vlrouter", net.ParseIP(localIP), | |
+ ofnet.OFNET_AGENT_VLAN_PORT, 6634, routerInfo...) | |
+ } else { | |
+ log.Errorf("Invalid Forwarding mode") | |
+ return nil, errors.New("Invalid forwarding mode. Expects 'bridge' or 'routing'") | |
+ } | |
+ | |
+ if err != nil { | |
+ log.Fatalf("Error initializing ofnet") | |
+ return nil, err | |
+ } | |
+ | |
+ // Add controller to the OVS | |
+ ctrlerIP := "127.0.0.1" | |
+ ctrlerPort := uint16(6634) | |
+ target := fmt.Sprintf("tcp:%s:%d", ctrlerIP, ctrlerPort) | |
+ if !sw.ovsdbDriver.IsControllerPresent(target) { | |
+ err = sw.ovsdbDriver.AddController(ctrlerIP, ctrlerPort) | |
+ if err != nil { | |
+ log.Fatalf("Error adding controller to OVS. Err: %v", err) | |
+ return nil, err | |
+ } | |
+ } | |
+ | |
+ log.Infof("Waiting for OVS switch to connect..") | |
+ | |
+ // Wait for a while for OVS switch to connect to ofnet agent | |
+ sw.ofnetAgent.WaitForSwitchConnection() | |
+ | |
+ log.Infof("Switch (vlan) connected.") | |
+ } | |
+ | |
return sw, nil | |
} | |
@@ -108,30 +158,28 @@ func (sw *OvsSwitch) Delete() { | |
} | |
// CreateNetwork creates a new network/vlan | |
-func (sw *OvsSwitch) CreateNetwork(pktTag uint16, extPktTag uint32) error { | |
- if sw.netType == "vxlan" { | |
- // Add the vlan/vni to ofnet | |
- err := sw.ofnetAgent.AddVlan(pktTag, extPktTag) | |
+func (sw *OvsSwitch) CreateNetwork(pktTag uint16, extPktTag uint32, defaultGw string) error { | |
+ // Add the vlan/vni to ofnet | |
+ if sw.ofnetAgent != nil { | |
+ err := sw.ofnetAgent.AddNetwork(pktTag, extPktTag, defaultGw) | |
if err != nil { | |
log.Errorf("Error adding vlan/vni %d/%d. Err: %v", pktTag, extPktTag, err) | |
return err | |
} | |
} | |
- | |
return nil | |
} | |
// DeleteNetwork deletes a network/vlan | |
-func (sw *OvsSwitch) DeleteNetwork(pktTag uint16, extPktTag uint32) error { | |
- if sw.netType == "vxlan" { | |
- // Delete vlan/vni mapping | |
- err := sw.ofnetAgent.RemoveVlan(pktTag, extPktTag) | |
+func (sw *OvsSwitch) DeleteNetwork(pktTag uint16, extPktTag uint32, gateway string) error { | |
+ // Delete vlan/vni mapping | |
+ if sw.ofnetAgent != nil { | |
+ err := sw.ofnetAgent.RemoveNetwork(pktTag, extPktTag, gateway) | |
if err != nil { | |
log.Errorf("Error removing vlan/vni %d/%d. Err: %v", pktTag, extPktTag, err) | |
return err | |
} | |
} | |
- | |
return nil | |
} | |
@@ -270,34 +318,37 @@ func (sw *OvsSwitch) CreatePort(intfName string, cfgEp *mastercfg.CfgEndpointSta | |
} | |
// Add the endpoint to ofnet | |
- if sw.netType == "vxlan" { | |
- // Get the openflow port number for the interface | |
- ofpPort, err := sw.ovsdbDriver.GetOfpPortNo(ovsPortName) | |
- if err != nil { | |
- log.Errorf("Could not find the OVS port %s. Err: %v", ovsPortName, err) | |
- return err | |
- } | |
+ if sw.ofnetAgent == nil { | |
+ log.Infof("Skipping adding endpoint to ofnet") | |
+ return nil | |
+ } | |
+ // Get the openflow port number for the interface | |
+ ofpPort, err := sw.ovsdbDriver.GetOfpPortNo(ovsPortName) | |
+ if err != nil { | |
+ log.Errorf("Could not find the OVS port %s. Err: %v", ovsPortName, err) | |
+ return err | |
+ } | |
- macAddr, _ := net.ParseMAC(cfgEp.MacAddress) | |
+ macAddr, _ := net.ParseMAC(cfgEp.MacAddress) | |
- // Build the endpoint info | |
- endpoint := ofnet.EndpointInfo{ | |
- PortNo: ofpPort, | |
- MacAddr: macAddr, | |
- Vlan: uint16(pktTag), | |
- IpAddr: net.ParseIP(cfgEp.IPAddress), | |
- EndpointGroup: cfgEp.EndpointGroupID, | |
- } | |
+ // Build the endpoint info | |
+ endpoint := ofnet.EndpointInfo{ | |
+ PortNo: ofpPort, | |
+ MacAddr: macAddr, | |
+ Vlan: uint16(pktTag), | |
+ IpAddr: net.ParseIP(cfgEp.IPAddress), | |
+ EndpointGroup: cfgEp.EndpointGroupID, | |
+ } | |
- log.Infof("Adding local endpoint: {%+v}", endpoint) | |
+ log.Infof("Adding local endpoint: {%+v}", endpoint) | |
- // Add the local port to ofnet | |
- err = sw.ofnetAgent.AddLocalEndpoint(endpoint) | |
- if err != nil { | |
- log.Errorf("Error adding local port %s to ofnet. Err: %v", ovsPortName, err) | |
- return err | |
- } | |
+ // Add the local port to ofnet | |
+ err = sw.ofnetAgent.AddLocalEndpoint(endpoint) | |
+ if err != nil { | |
+ log.Errorf("Error adding local port %s to ofnet. Err: %v", ovsPortName, err) | |
+ return err | |
} | |
+ // } | |
return nil | |
} | |
@@ -308,33 +359,34 @@ func (sw *OvsSwitch) UpdatePort(intfName string, cfgEp *mastercfg.CfgEndpointSta | |
ovsPortName := getOvsPostName(intfName) | |
// Add the endpoint to ofnet | |
- if sw.netType == "vxlan" { | |
- // Get the openflow port number for the interface | |
- ofpPort, err := sw.ovsdbDriver.GetOfpPortNo(ovsPortName) | |
- if err != nil { | |
- log.Errorf("Could not find the OVS port %s. Err: %v", ovsPortName, err) | |
- return err | |
- } | |
- | |
- macAddr, _ := net.ParseMAC(cfgEp.MacAddress) | |
+ // Get the openflow port number for the interface | |
+ ofpPort, err := sw.ovsdbDriver.GetOfpPortNo(ovsPortName) | |
+ if err != nil { | |
+ log.Errorf("Could not find the OVS port %s. Err: %v", ovsPortName, err) | |
+ return err | |
+ } | |
- // Build the endpoint info | |
- endpoint := ofnet.EndpointInfo{ | |
- PortNo: ofpPort, | |
- MacAddr: macAddr, | |
- Vlan: uint16(pktTag), | |
- IpAddr: net.ParseIP(cfgEp.IPAddress), | |
- EndpointGroup: cfgEp.EndpointGroupID, | |
- } | |
+ macAddr, _ := net.ParseMAC(cfgEp.MacAddress) | |
- // Add the local port to ofnet | |
- err = sw.ofnetAgent.AddLocalEndpoint(endpoint) | |
- if err != nil { | |
- log.Errorf("Error adding local port %s to ofnet. Err: %v", ovsPortName, err) | |
- return err | |
- } | |
+ // Build the endpoint info | |
+ endpoint := ofnet.EndpointInfo{ | |
+ PortNo: ofpPort, | |
+ MacAddr: macAddr, | |
+ Vlan: uint16(pktTag), | |
+ IpAddr: net.ParseIP(cfgEp.IPAddress), | |
+ EndpointGroup: cfgEp.EndpointGroupID, | |
} | |
+ // Add the local port to ofnet | |
+ if sw.ofnetAgent == nil { | |
+ log.Infof("Skipping adding localport to ofnet") | |
+ return nil | |
+ } | |
+ err = sw.ofnetAgent.AddLocalEndpoint(endpoint) | |
+ if err != nil { | |
+ log.Errorf("Error adding local port %s to ofnet. Err: %v", ovsPortName, err) | |
+ return err | |
+ } | |
return nil | |
} | |
@@ -362,14 +414,14 @@ func (sw *OvsSwitch) DeletePort(epOper *OvsOperEndpointState) error { | |
} | |
// Remove info from ofnet | |
- if sw.netType == "vxlan" { | |
- // Get the openflow port number for the interface | |
- ofpPort, err := sw.ovsdbDriver.GetOfpPortNo(ovsPortName) | |
- if err != nil { | |
- log.Errorf("Could not find the OVS port %s. Err: %v", ovsPortName, err) | |
- return err | |
- } | |
+ // Get the openflow port number for the interface | |
+ ofpPort, err := sw.ovsdbDriver.GetOfpPortNo(ovsPortName) | |
+ if err != nil { | |
+ log.Errorf("Could not find the OVS port %s. Err: %v", ovsPortName, err) | |
+ return err | |
+ } | |
+ if sw.ofnetAgent != nil { | |
err = sw.ofnetAgent.RemoveLocalEndpoint(ofpPort) | |
if err != nil { | |
log.Errorf("Error removing port %s from ofnet. Err: %v", ovsPortName, err) | |
@@ -377,7 +429,7 @@ func (sw *OvsSwitch) DeletePort(epOper *OvsOperEndpointState) error { | |
} | |
// Delete it from ovsdb | |
- err := sw.ovsdbDriver.DeletePort(ovsPortName) | |
+ err = sw.ovsdbDriver.DeletePort(ovsPortName) | |
if err != nil { | |
return err | |
} | |
@@ -418,10 +470,12 @@ func (sw *OvsSwitch) CreateVtep(vtepIP string) error { | |
} | |
// Add info about VTEP port to ofnet | |
- err = sw.ofnetAgent.AddVtepPort(ofpPort, net.ParseIP(vtepIP)) | |
- if err != nil { | |
- log.Errorf("Error adding VTEP port %s to ofnet. Err: %v", intfName, err) | |
- return err | |
+ if sw.ofnetAgent != nil { | |
+ err = sw.ofnetAgent.AddVtepPort(ofpPort, net.ParseIP(vtepIP)) | |
+ if err != nil { | |
+ log.Errorf("Error adding VTEP port %s to ofnet. Err: %v", intfName, err) | |
+ return err | |
+ } | |
} | |
return nil | |
@@ -442,10 +496,12 @@ func (sw *OvsSwitch) DeleteVtep(vtepIP string) error { | |
} | |
// Add info about VTEP port to ofnet | |
- err = sw.ofnetAgent.RemoveVtepPort(ofpPort, net.ParseIP(vtepIP)) | |
- if err != nil { | |
- log.Errorf("Error deleting VTEP port %s to ofnet. Err: %v", intfName, err) | |
- return err | |
+ if sw.ofnetAgent != nil { | |
+ err = sw.ofnetAgent.RemoveVtepPort(ofpPort, net.ParseIP(vtepIP)) | |
+ if err != nil { | |
+ log.Errorf("Error deleting VTEP port %s to ofnet. Err: %v", intfName, err) | |
+ return err | |
+ } | |
} | |
// ask ovsdb to delete the VTEP | |
@@ -495,10 +551,12 @@ func (sw *OvsSwitch) AddMaster(node core.ServiceInfo) error { | |
} | |
// Add the master | |
- err := sw.ofnetAgent.AddMaster(&masterInfo, &resp) | |
- if err != nil { | |
- log.Errorf("Error adding ofnet master %+v. Err: %v", masterInfo, err) | |
- return err | |
+ if sw.ofnetAgent != nil { | |
+ err := sw.ofnetAgent.AddMaster(&masterInfo, &resp) | |
+ if err != nil { | |
+ log.Errorf("Error adding ofnet master %+v. Err: %v", masterInfo, err) | |
+ return err | |
+ } | |
} | |
return nil | |
@@ -513,11 +571,39 @@ func (sw *OvsSwitch) DeleteMaster(node core.ServiceInfo) error { | |
} | |
// remove the master | |
- err := sw.ofnetAgent.RemoveMaster(&masterInfo) | |
- if err != nil { | |
- log.Errorf("Error deleting ofnet master %+v. Err: %v", masterInfo, err) | |
- return err | |
+ if sw.ofnetAgent != nil { | |
+ err := sw.ofnetAgent.RemoveMaster(&masterInfo) | |
+ if err != nil { | |
+ log.Errorf("Error deleting ofnet master %+v. Err: %v", masterInfo, err) | |
+ return err | |
+ } | |
} | |
return nil | |
} | |
+ | |
+// AddBgpNeighbors adds a bgp neighbor to host | |
+func (sw *OvsSwitch) AddBgpNeighbors(hostname string, As string, neighbor string) error { | |
+ if sw.netType == "vlan" && sw.ofnetAgent != nil { | |
+ err := sw.ofnetAgent.AddBgpNeighbors(As, neighbor) | |
+ if err != nil { | |
+ log.Errorf("Error adding BGP server") | |
+ return err | |
+ } | |
+ } | |
+ | |
+ return nil | |
+} | |
+ | |
+// DeleteBgpNeighbors deletes bgp config for host | |
+func (sw *OvsSwitch) DeleteBgpNeighbors() error { | |
+ if sw.netType == "vlan" && sw.ofnetAgent != nil { | |
+ // Delete vlan/vni mapping | |
+ err := sw.ofnetAgent.DeleteBgpNeighbors() | |
+ if err != nil { | |
+ log.Errorf("Error removing bgp server Err: %v", err) | |
+ return err | |
+ } | |
+ } | |
+ return nil | |
+} | |
diff --git a/drivers/ovsbgpstate.go b/drivers/ovsbgpstate.go | |
new file mode 100755 | |
index 0000000..9c1e242 | |
--- /dev/null | |
+++ b/drivers/ovsbgpstate.go | |
@@ -0,0 +1,63 @@ | |
+/*** | |
+Copyright 2014 Cisco Systems Inc. All rights reserved. | |
+ | |
+Licensed under the Apache License, Version 2.0 (the "License"); | |
+you may not use this file except in compliance with the License. | |
+You may obtain a copy of the License at | |
+http://www.apache.org/licenses/LICENSE-2.0 | |
+ | |
+Unless required by applicable law or agreed to in writing, software | |
+distributed under the License is distributed on an "AS IS" BASIS, | |
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+See the License for the specific language governing permissions and | |
+limitations under the License. | |
+*/ | |
+ | |
+package drivers | |
+ | |
+import ( | |
+ "encoding/json" | |
+ "fmt" | |
+ "github.com/contiv/netplugin/core" | |
+ "github.com/contiv/netplugin/netmaster/mastercfg" | |
+ "reflect" | |
+) | |
+ | |
+// OvsOperBgpState is the necessary data used to perform operations on | |
+//neighbor bgp config. | |
+type OvsOperBgpState struct { | |
+ core.CommonState | |
+ Name string `json:"name"` | |
+ As string `json:"As"` | |
+ Neighbor string `json:"neighbor"` | |
+} | |
+ | |
+// Matches matches the fields updated from configuration state | |
+func (s *OvsOperBgpState) Matches(c *mastercfg.CfgBgpState) bool { | |
+ return s.Name == c.Name && | |
+ s.As == c.As && | |
+ reflect.DeepEqual(s.Neighbor, c.Neighbor) | |
+} | |
+ | |
+// Write the state. | |
+func (s *OvsOperBgpState) Write() error { | |
+ key := fmt.Sprintf(bgpOperPath, s.ID) | |
+ return s.StateDriver.WriteState(key, s, json.Marshal) | |
+} | |
+ | |
+// Read the state for a given identifier. | |
+func (s *OvsOperBgpState) Read(id string) error { | |
+ key := fmt.Sprintf(bgpOperPath, id) | |
+ return s.StateDriver.ReadState(key, s, json.Unmarshal) | |
+} | |
+ | |
+// ReadAll reads all state into separate objects. | |
+func (s *OvsOperBgpState) ReadAll() ([]core.State, error) { | |
+ return s.StateDriver.ReadAllState(bgpOperPathPrefix, s, json.Unmarshal) | |
+} | |
+ | |
+// Clear removes the state. | |
+func (s *OvsOperBgpState) Clear() error { | |
+ key := fmt.Sprintf(bgpOperPath, s.ID) | |
+ return s.StateDriver.ClearState(key) | |
+} | |
diff --git a/drivers/ovsconstants.go b/drivers/ovsconstants.go | |
old mode 100644 | |
new mode 100755 | |
index 89409d2..c29c1e4 | |
--- a/drivers/ovsconstants.go | |
+++ b/drivers/ovsconstants.go | |
@@ -31,4 +31,6 @@ const ( | |
endpointOperPathPrefix = StateOperPath + "eps/" | |
networkOperPath = networkOperPathPrefix + "%s" | |
endpointOperPath = endpointOperPathPrefix + "%s" | |
+ bgpOperPathPrefix = StateOperPath + "bgps/" | |
+ bgpOperPath = bgpOperPathPrefix + "%s" | |
) | |
diff --git a/drivers/ovsdbDriver.go b/drivers/ovsdbDriver.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/drivers/ovsdriver.go b/drivers/ovsdriver.go | |
old mode 100644 | |
new mode 100755 | |
index 5421b9d..1d6a10e | |
--- a/drivers/ovsdriver.go | |
+++ b/drivers/ovsdriver.go | |
@@ -115,13 +115,14 @@ func (d *OvsDriver) Init(config *core.Config, info *core.InstanceInfo) error { | |
d.switchDb = make(map[string]*OvsSwitch) | |
// Create Vxlan switch | |
- d.switchDb["vxlan"], err = NewOvsSwitch(vxlanBridgeName, "vxlan", info.VtepIP) | |
+ d.switchDb["vxlan"], err = NewOvsSwitch(vxlanBridgeName, "vxlan", info.VtepIP, | |
+ info.FwdMode) | |
if err != nil { | |
log.Fatalf("Error creating vlan switch. Err: %v", err) | |
} | |
- | |
// Create Vlan switch | |
- d.switchDb["vlan"], err = NewOvsSwitch(vlanBridgeName, "vlan", info.VtepIP) | |
+ d.switchDb["vlan"], err = NewOvsSwitch(vlanBridgeName, "vlan", info.VtepIP, | |
+ info.FwdMode, info.RouterIP, info.VlanIntf) | |
if err != nil { | |
log.Fatalf("Error creating vlan switch. Err: %v", err) | |
} | |
@@ -169,11 +170,11 @@ func (d *OvsDriver) CreateNetwork(id string) error { | |
sw = d.switchDb["vlan"] | |
} | |
- return sw.CreateNetwork(uint16(cfgNw.PktTag), uint32(cfgNw.ExtPktTag)) | |
+ return sw.CreateNetwork(uint16(cfgNw.PktTag), uint32(cfgNw.ExtPktTag), cfgNw.Gateway) | |
} | |
// DeleteNetwork deletes a network by named identifier | |
-func (d *OvsDriver) DeleteNetwork(id, encap string, pktTag, extPktTag int) error { | |
+func (d *OvsDriver) DeleteNetwork(id, encap string, pktTag, extPktTag int,gateway string) error { | |
log.Infof("delete net %s \n", id) | |
// Find the switch based on network type | |
@@ -184,7 +185,7 @@ func (d *OvsDriver) DeleteNetwork(id, encap string, pktTag, extPktTag int) error | |
sw = d.switchDb["vlan"] | |
} | |
- return sw.DeleteNetwork(uint16(pktTag), uint32(extPktTag)) | |
+ return sw.DeleteNetwork(uint16(pktTag), uint32(extPktTag),gateway) | |
} | |
// CreateEndpoint creates an endpoint by named identifier | |
@@ -352,6 +353,7 @@ func (d *OvsDriver) AddPeerHost(node core.ServiceInfo) error { | |
// Add the VTEP for the peer in vxlan switch. | |
err := d.switchDb["vxlan"].CreateVtep(node.HostAddr) | |
+ | |
if err != nil { | |
log.Errorf("Error adding the VTEP %s. Err: %s", node.HostAddr, err) | |
return err | |
@@ -371,6 +373,7 @@ func (d *OvsDriver) DeletePeerHost(node core.ServiceInfo) error { | |
// Add the VTEP for the peer in vxlan switch. | |
err := d.switchDb["vxlan"].DeleteVtep(node.HostAddr) | |
+ | |
if err != nil { | |
log.Errorf("Error deleting the VTEP %s. Err: %s", node.HostAddr, err) | |
return err | |
@@ -384,11 +387,15 @@ func (d *OvsDriver) AddMaster(node core.ServiceInfo) error { | |
log.Infof("AddMaster for %+v", node) | |
// Add master to vlan and vxlan datapaths | |
- err := d.switchDb["vxlan"].AddMaster(node) | |
+ err := d.switchDb["vlan"].AddMaster(node) | |
if err != nil { | |
return err | |
} | |
+ err = d.switchDb["vxlan"].AddMaster(node) | |
+ if err != nil { | |
+ return err | |
+ } | |
return nil | |
} | |
@@ -397,10 +404,46 @@ func (d *OvsDriver) DeleteMaster(node core.ServiceInfo) error { | |
log.Infof("DeleteMaster for %+v", node) | |
// Delete master from vlan and vxlan datapaths | |
- err := d.switchDb["vxlan"].DeleteMaster(node) | |
+ err := d.switchDb["vlan"].DeleteMaster(node) | |
if err != nil { | |
return err | |
} | |
+ err = d.switchDb["vxlan"].DeleteMaster(node) | |
+ if err != nil { | |
+ return err | |
+ } | |
return nil | |
} | |
+ | |
+// AddBgpNeighbors adds bgp neighbor by named identifier | |
+func (d *OvsDriver) AddBgpNeighbors(id string) error { | |
+ var sw *OvsSwitch | |
+ | |
+ cfg := mastercfg.CfgBgpState{} | |
+ cfg.StateDriver = d.oper.StateDriver | |
+ log.Info("Reading from etcd State %s", id) | |
+ err := cfg.Read(id) | |
+ if err != nil { | |
+ log.Errorf("Failed to read router state %s \n", cfg.Name) | |
+ return err | |
+ } | |
+ log.Infof("create Bgp Server %s \n", cfg.Name) | |
+ | |
+ // Find the switch based on network type | |
+ sw = d.switchDb["vlan"] | |
+ | |
+ return sw.AddBgpNeighbors(cfg.Name, cfg.As, cfg.Neighbor) | |
+} | |
+ | |
+// DeleteBgpNeighbors deletes a bgp neighbor by named identifier | |
+func (d *OvsDriver) DeleteBgpNeighbors(id string) error { | |
+ log.Infof("delete router state %s \n", id) | |
+ //FixME: We are not maintaining oper state for Bgp | |
+ //Need to Revisit again | |
+ // Find the switch based on network type | |
+ var sw *OvsSwitch | |
+ | |
+ sw = d.switchDb["vlan"] | |
+ return sw.DeleteBgpNeighbors() | |
+} | |
diff --git a/drivers/ovsdriver_test.go b/drivers/ovsdriver_test.go | |
old mode 100644 | |
new mode 100755 | |
index 80cebad..8552492 | |
--- a/drivers/ovsdriver_test.go | |
+++ b/drivers/ovsdriver_test.go | |
@@ -166,11 +166,12 @@ func initOvsDriver(t *testing.T) *OvsDriver { | |
ovsConfig := &OvsDriverConfig{} | |
ovsConfig.Ovs.DbIP = "" | |
ovsConfig.Ovs.DbPort = 0 | |
+ fMode := "bridge" | |
config := &core.Config{V: ovsConfig} | |
stateDriver := &state.FakeStateDriver{} | |
stateDriver.Init(nil) | |
instInfo := &core.InstanceInfo{HostLabel: testHostLabel, | |
- StateDriver: stateDriver} | |
+ StateDriver: stateDriver, FwdMode: fMode} | |
err := createCommonState(stateDriver) | |
if err != nil { | |
@@ -195,11 +196,12 @@ func TestOvsDriverInitStatefulStart(t *testing.T) { | |
ovsConfig := &OvsDriverConfig{} | |
ovsConfig.Ovs.DbIP = "" | |
ovsConfig.Ovs.DbPort = 0 | |
+ fMode := "bridge" | |
config := &core.Config{V: ovsConfig} | |
stateDriver := &state.FakeStateDriver{} | |
stateDriver.Init(nil) | |
instInfo := &core.InstanceInfo{HostLabel: testHostLabelStateful, | |
- StateDriver: stateDriver} | |
+ StateDriver: stateDriver, FwdMode: fMode} | |
operOvs := &OvsDriverOperState{CurrPortNum: 10} | |
operOvs.StateDriver = stateDriver | |
@@ -248,8 +250,10 @@ func TestOvsDriverInitInvalidState(t *testing.T) { | |
ovsConfig := &OvsDriverConfig{} | |
ovsConfig.Ovs.DbIP = "" | |
ovsConfig.Ovs.DbPort = 0 | |
+ fMode := "bridge" | |
config := &core.Config{V: ovsConfig} | |
- instInfo := &core.InstanceInfo{HostLabel: testHostLabel, StateDriver: nil} | |
+ instInfo := &core.InstanceInfo{HostLabel: testHostLabel, StateDriver: nil, | |
+ FwdMode: fMode} | |
err := driver.Init(config, instInfo) | |
if err == nil { | |
diff --git a/drivers/ovsendpointstate.go b/drivers/ovsendpointstate.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/drivers/ovsendpointstate_test.go b/drivers/ovsendpointstate_test.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/netctl/commands.go b/netctl/commands.go | |
old mode 100644 | |
new mode 100755 | |
index 699cd36..d4cb8bd | |
--- a/netctl/commands.go | |
+++ b/netctl/commands.go | |
@@ -244,4 +244,46 @@ var Commands = []cli.Command{ | |
}, | |
}, | |
}, | |
+ { | |
+ Name: "bgp", | |
+ Usage: "router capability configuration", | |
+ Subcommands: []cli.Command{ | |
+ { | |
+ Name: "delete", | |
+ Usage: "Delete Bgp neighbor", | |
+ ArgsUsage: "[router]", | |
+ Flags: []cli.Flag{ | |
+ cli.StringFlag{ | |
+ Name: "host", | |
+ Usage: "host name", | |
+ }, | |
+ cli.StringFlag{ | |
+ Name: "neighbors", | |
+ Usage: "Bgp neighbor to be deleted", | |
+ }, | |
+ }, | |
+ Action: deleteBgpNeighbors, | |
+ }, | |
+ { | |
+ Name: "add", | |
+ Usage: "Add router capability configuration.", | |
+ ArgsUsage: " ", | |
+ Flags: []cli.Flag{ | |
+ cli.StringFlag{ | |
+ Name: "host", | |
+ Usage: "host name", | |
+ }, | |
+ cli.StringFlag{ | |
+ Name: "as", | |
+ Usage: "AS id", | |
+ }, | |
+ cli.StringFlag{ | |
+ Name: "neighbor", | |
+ Usage: "Bgp neighbor to be added", | |
+ }, | |
+ }, | |
+ Action: addBgpNeighbors, | |
+ }, | |
+ }, | |
+ }, | |
} | |
diff --git a/netctl/exit.go b/netctl/exit.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/netctl/http.go b/netctl/http.go | |
old mode 100644 | |
new mode 100755 | |
index 3251284..8b1e207 | |
--- a/netctl/http.go | |
+++ b/netctl/http.go | |
@@ -43,12 +43,15 @@ func ruleURL(ctx *cli.Context) string { | |
return fmt.Sprintf("%s/api/rules/", baseURL(ctx)) | |
} | |
+func bgpURL(ctx *cli.Context) string { | |
+ return fmt.Sprintf("%s/api/Bgps/", baseURL(ctx)) | |
+} | |
+ | |
func writeBody(resp *http.Response, ctx *cli.Context) { | |
content, err := ioutil.ReadAll(resp.Body) | |
if err != nil { | |
errExit(ctx, exitIO, err.Error(), false) | |
} | |
- | |
os.Stderr.Write(content) | |
} | |
diff --git a/netctl/netctl.go b/netctl/netctl.go | |
old mode 100644 | |
new mode 100755 | |
index 2feab24..8a06995 | |
--- a/netctl/netctl.go | |
+++ b/netctl/netctl.go | |
@@ -401,3 +401,71 @@ func dumpList(ctx *cli.Context, list []map[string]interface{}) { | |
os.Stdout.Write(content) | |
os.Stdout.WriteString("\n") | |
} | |
+ | |
+//addBgpNeighbors is a netctl interface routine to add | |
+//bgp neighbor | |
+ | |
+func addBgpNeighbors(ctx *cli.Context) { | |
+ argCheck(0, ctx) | |
+ | |
+ hostname := ctx.String("host") | |
+ asid := ctx.String("as") | |
+ | |
+ neighbor := ctx.String("neighbor") | |
+ url := fmt.Sprintf("%s%s/", bgpURL(ctx), hostname) | |
+ | |
+ out := map[string]interface{}{ | |
+ "Name": hostname, | |
+ "as": asid, | |
+ "neighbor": neighbor, | |
+ } | |
+ postMap(ctx, url, out) | |
+} | |
+ | |
+//deleteBgpNeighbors is a netctl interface routine to delete | |
+//bgp neighbor | |
+ | |
+func deleteBgpNeighbors(ctx *cli.Context) { | |
+ argCheck(0, ctx) | |
+ | |
+ hostname := ctx.String("host") | |
+ logrus.Infof("Deleting router config %s:%s", hostname) | |
+ | |
+ deleteURL(ctx, fmt.Sprintf("%s%s/", bgpURL(ctx), hostname)) | |
+} | |
+ | |
+//listBgpNeighbors is netctl interface routine to list | |
+//Bgp neighbor configs for a given host | |
+func listBgpNeighbors(ctx *cli.Context) { | |
+ argCheck(0, ctx) | |
+ | |
+ hostname := ctx.String("host") | |
+ | |
+ list := getList(ctx, bgpURL(ctx)) | |
+ filtered := []map[string]interface{}{} | |
+ | |
+ for _, group := range list { | |
+ if group["name"] == hostname || ctx.Bool("all") { | |
+ filtered = append(filtered, group) | |
+ } | |
+ } | |
+ | |
+ if ctx.Bool("json") { | |
+ dumpList(ctx, filtered) | |
+ } else { | |
+ | |
+ writer := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0) | |
+ defer writer.Flush() | |
+ writer.Write([]byte("HostName\tNeighbor\tAS\n")) | |
+ writer.Write([]byte("---------\t--------\t-------\n")) | |
+ for _, group := range filtered { | |
+ fmt.Println(group) | |
+ writer.Write( | |
+ []byte(fmt.Sprintf("%v\t%v\t%v\t\n", | |
+ group["name"], | |
+ group["neighbor"], | |
+ group["AS"], | |
+ ))) | |
+ } | |
+ } | |
+} | |
diff --git a/netctl/netctl/main.go b/netctl/netctl/main.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/netmaster/intent/config.go b/netmaster/intent/config.go | |
old mode 100644 | |
new mode 100755 | |
index cc088e8..140497a | |
--- a/netmaster/intent/config.go | |
+++ b/netmaster/intent/config.go | |
@@ -72,8 +72,14 @@ type ConfigTenant struct { | |
AllocSubnetLen uint | |
VLANs string | |
VXLANs string | |
+ Networks []ConfigNetwork | |
+} | |
- Networks []ConfigNetwork | |
+//ConfigBgp keeps bgp specific configs | |
+type ConfigBgp struct { | |
+ Name string | |
+ As string | |
+ Neighbor string | |
} | |
// Config is the top level configuration | |
@@ -83,4 +89,5 @@ type Config struct { | |
Tenants []ConfigTenant | |
// (optional) host bindings | |
HostBindings []ConfigEP | |
+ RouterInfo []ConfigBgp | |
} | |
diff --git a/netmaster/master/bgp.go b/netmaster/master/bgp.go | |
new file mode 100755 | |
index 0000000..4ed2255 | |
--- /dev/null | |
+++ b/netmaster/master/bgp.go | |
@@ -0,0 +1,60 @@ | |
+/*** | |
+Copyright 2014 Cisco Systems Inc. All rights reserved. | |
+ | |
+Licensed under the Apache License, Version 2.0 (the "License"); | |
+you may not use this file except in compliance with the License. | |
+You may obtain a copy of the License at | |
+http://www.apache.org/licenses/LICENSE-2.0 | |
+ | |
+Unless required by applicable law or agreed to in writing, software | |
+distributed under the License is distributed on an "AS IS" BASIS, | |
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+See the License for the specific language governing permissions and | |
+limitations under the License. | |
+*/ | |
+ | |
+package master | |
+ | |
+import ( | |
+ log "github.com/Sirupsen/logrus" | |
+ "github.com/contiv/netplugin/core" | |
+ "github.com/contiv/netplugin/netmaster/intent" | |
+ "github.com/contiv/netplugin/netmaster/mastercfg" | |
+) | |
+ | |
+//AddBgpNeighbors adds to the etcd state | |
+func AddBgpNeighbors(stateDriver core.StateDriver, bgpCfg *intent.ConfigBgp) error { | |
+ | |
+ log.Infof("Adding bgp neighbor {%v}", bgpCfg) | |
+ bgpState := &mastercfg.CfgBgpState{} | |
+ bgpState.Name = bgpCfg.Name | |
+ bgpState.As = bgpCfg.As | |
+ bgpState.Neighbor = bgpCfg.Neighbor | |
+ bgpState.StateDriver = stateDriver | |
+ bgpState.ID = bgpCfg.Name | |
+ err := bgpState.Write() | |
+ | |
+ if err != nil { | |
+ return err | |
+ } | |
+ return nil | |
+} | |
+ | |
+//DeleteBgpNeighbors deletes from etcd state | |
+func DeleteBgpNeighbors(stateDriver core.StateDriver, hostname string) error { | |
+ log.Infof("Deleting bgp neighbor for {%v}", hostname) | |
+ bgpState := &mastercfg.CfgBgpState{} | |
+ bgpState.StateDriver = stateDriver | |
+ err := bgpState.Read(hostname) | |
+ if err != nil { | |
+ log.Errorf("Error reading bgp config for hostname %s", hostname) | |
+ return err | |
+ } | |
+ err = bgpState.Clear() | |
+ if err != nil { | |
+ log.Errorf("Error deleing Bgp config for hostname %s", hostname) | |
+ return err | |
+ } | |
+ return nil | |
+ | |
+} | |
diff --git a/netmaster/master/netmaster.go b/netmaster/master/netmaster.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/netmaster/mastercfg/bgpState_test.go b/netmaster/mastercfg/bgpState_test.go | |
new file mode 100755 | |
index 0000000..9255a39 | |
--- /dev/null | |
+++ b/netmaster/mastercfg/bgpState_test.go | |
@@ -0,0 +1,119 @@ | |
+/*** | |
+Copyright 2014 Cisco Systems Inc. All rights reserved. | |
+ | |
+Licensed under the Apache License, Version 2.0 (the "License"); | |
+you may not use this file except in compliance with the License. | |
+You may obtain a copy of the License at | |
+http://www.apache.org/licenses/LICENSE-2.0 | |
+ | |
+Unless required by applicable law or agreed to in writing, software | |
+distributed under the License is distributed on an "AS IS" BASIS, | |
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+See the License for the specific language governing permissions and | |
+limitations under the License. | |
+*/ | |
+ | |
+package mastercfg | |
+ | |
+import ( | |
+ "github.com/contiv/netplugin/core" | |
+ "testing" | |
+) | |
+ | |
+const ( | |
+ testhostID = "contivhost" | |
+ bgpCfgKey = bgpConfigPathPrefix + testhostID | |
+) | |
+ | |
+type testBgpStateDriver struct{} | |
+ | |
+var bgpStateDriver = &testBgpStateDriver{} | |
+ | |
+func (d *testBgpStateDriver) Init(config *core.Config) error { | |
+ return core.Errorf("Shouldn't be called!") | |
+} | |
+ | |
+func (d *testBgpStateDriver) Deinit() { | |
+} | |
+ | |
+func (d *testBgpStateDriver) Write(key string, value []byte) error { | |
+ return core.Errorf("Shouldn't be called!") | |
+} | |
+ | |
+func (d *testBgpStateDriver) Read(key string) ([]byte, error) { | |
+ return []byte{}, core.Errorf("Shouldn't be called!") | |
+} | |
+ | |
+func (d *testBgpStateDriver) ReadAll(baseKey string) ([][]byte, error) { | |
+ return [][]byte{}, core.Errorf("Shouldn't be called!") | |
+} | |
+ | |
+func (d *testBgpStateDriver) WatchAll(baseKey string, rsps chan [2][]byte) error { | |
+ return core.Errorf("not supported") | |
+} | |
+ | |
+func (d *testBgpStateDriver) validateKey(key string) error { | |
+ if key != bgpCfgKey { | |
+ return core.Errorf("Unexpected key. recvd: %s expected: %s ", | |
+ key, bgpCfgKey) | |
+ } | |
+ | |
+ return nil | |
+} | |
+ | |
+func (d *testBgpStateDriver) ClearState(key string) error { | |
+ return d.validateKey(key) | |
+} | |
+ | |
+func (d *testBgpStateDriver) ReadState(key string, value core.State, | |
+ unmarshal func([]byte, interface{}) error) error { | |
+ return d.validateKey(key) | |
+} | |
+ | |
+func (d *testBgpStateDriver) ReadAllState(key string, value core.State, | |
+ unmarshal func([]byte, interface{}) error) ([]core.State, error) { | |
+ return nil, core.Errorf("Shouldn't be called!") | |
+} | |
+ | |
+func (d *testBgpStateDriver) WatchAllState(baseKey string, sType core.State, | |
+ unmarshal func([]byte, interface{}) error, rsps chan core.WatchState) error { | |
+ return core.Errorf("not supported") | |
+} | |
+ | |
+func (d *testBgpStateDriver) WriteState(key string, value core.State, | |
+ marshal func(interface{}) ([]byte, error)) error { | |
+ return d.validateKey(key) | |
+} | |
+ | |
+func TestCfgBgpStateRead(t *testing.T) { | |
+ bgpCfg := &CfgBgpState{} | |
+ bgpCfg.StateDriver = bgpStateDriver | |
+ | |
+ err := bgpCfg.Read(testhostID) | |
+ if err != nil { | |
+ t.Fatalf("read config state failed. Error: %s", err) | |
+ } | |
+} | |
+ | |
+func TestCfgBgpStateWrite(t *testing.T) { | |
+ | |
+ bgpCfg := &CfgBgpState{} | |
+ bgpCfg.StateDriver = bgpStateDriver | |
+ bgpCfg.Name = testhostID | |
+ | |
+ err := bgpCfg.Write() | |
+ if err != nil { | |
+ t.Fatalf("write config state failed. Error: %s", err) | |
+ } | |
+} | |
+ | |
+func TestCfgBgpStateClear(t *testing.T) { | |
+ bgpCfg := &CfgBgpState{} | |
+ bgpCfg.StateDriver = bgpStateDriver | |
+ bgpCfg.Name = testhostID | |
+ | |
+ err := bgpCfg.Clear() | |
+ if err != nil { | |
+ t.Fatalf("clear config state failed. Error: %s", err) | |
+ } | |
+} | |
diff --git a/netmaster/mastercfg/routerState.go b/netmaster/mastercfg/routerState.go | |
new file mode 100755 | |
index 0000000..d6d99a3 | |
--- /dev/null | |
+++ b/netmaster/mastercfg/routerState.go | |
@@ -0,0 +1,64 @@ | |
+/*** | |
+Copyright 2014 Cisco Systems Inc. All rights reserved. | |
+ | |
+Licensed under the Apache License, Version 2.0 (the "License"); | |
+you may not use this file except in compliance with the License. | |
+You may obtain a copy of the License at | |
+http://www.apache.org/licenses/LICENSE-2.0 | |
+ | |
+Unless required by applicable law or agreed to in writing, software | |
+distributed under the License is distributed on an "AS IS" BASIS, | |
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
+See the License for the specific language governing permissions and | |
+limitations under the License. | |
+*/ | |
+ | |
+package mastercfg | |
+ | |
+import ( | |
+ "encoding/json" | |
+ "fmt" | |
+ "github.com/contiv/netplugin/core" | |
+) | |
+ | |
+const ( | |
+ bgpConfigPathPrefix = StateConfigPath + "bgp/" | |
+ bgpConfigPath = bgpConfigPathPrefix + "%s" | |
+) | |
+ | |
+// CfgBgpState is the router Bgp configuration for the host | |
+type CfgBgpState struct { | |
+ core.CommonState | |
+ Name string `json:"name"` | |
+ As string `json:"as"` | |
+ Neighbor string `json:"neighbor"` | |
+} | |
+ | |
+// Write the state | |
+func (s *CfgBgpState) Write() error { | |
+ key := fmt.Sprintf(bgpConfigPath, s.Name) | |
+ return s.StateDriver.WriteState(key, s, json.Marshal) | |
+} | |
+ | |
+// Read the state in for a given ID. | |
+func (s *CfgBgpState) Read(id string) error { | |
+ key := fmt.Sprintf(bgpConfigPath, id) | |
+ return s.StateDriver.ReadState(key, s, json.Unmarshal) | |
+} | |
+ | |
+// ReadAll reads all the state for master bgp configurations and returns it. | |
+func (s *CfgBgpState) ReadAll() ([]core.State, error) { | |
+ return s.StateDriver.ReadAllState(bgpConfigPathPrefix, s, json.Unmarshal) | |
+} | |
+ | |
+// Clear removes the configuration from the state store. | |
+func (s *CfgBgpState) Clear() error { | |
+ key := fmt.Sprintf(bgpConfigPath, s.Name) | |
+ return s.StateDriver.ClearState(key) | |
+} | |
+ | |
+// WatchAll state transitions and send them through the channel. | |
+func (s *CfgBgpState) WatchAll(rsps chan core.WatchState) error { | |
+ return s.StateDriver.WatchAllState(bgpConfigPathPrefix, s, json.Unmarshal, | |
+ rsps) | |
+} | |
diff --git a/netmaster/objApi/apiController.go b/netmaster/objApi/apiController.go | |
old mode 100644 | |
new mode 100755 | |
index 36192a5..50e9404 | |
--- a/netmaster/objApi/apiController.go | |
+++ b/netmaster/objApi/apiController.go | |
@@ -54,7 +54,7 @@ func NewAPIController(router *mux.Router) *APIController { | |
contivModel.RegisterServiceCallbacks(ctrler) | |
contivModel.RegisterServiceInstanceCallbacks(ctrler) | |
contivModel.RegisterTenantCallbacks(ctrler) | |
- | |
+ contivModel.RegisterBgpCallbacks(ctrler) | |
// Register routes | |
contivModel.AddRoutes(router) | |
@@ -767,3 +767,57 @@ func (ac *APIController) TenantDelete(tenant *contivModel.Tenant) error { | |
return nil | |
} | |
+ | |
+//BgpCreate add bgp neighbor | |
+func (ac *APIController) BgpCreate(bgpNeighborCfg *contivModel.Bgp) error { | |
+ log.Infof("Received BgpCreate: %+v", bgpNeighborCfg) | |
+ | |
+ if bgpNeighborCfg.Name == "" { | |
+ return core.Errorf("Invalid host name") | |
+ } | |
+ | |
+ // Get the state driver | |
+ stateDriver, err := utils.GetStateDriver() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Build bgp config | |
+ bgpCfg := intent.ConfigBgp{ | |
+ Name: bgpNeighborCfg.Name, | |
+ As: bgpNeighborCfg.AS, | |
+ Neighbor: bgpNeighborCfg.Neighbor, | |
+ } | |
+ | |
+ // Add the Bgp neighbor | |
+ err = master.AddBgpNeighbors(stateDriver, &bgpCfg) | |
+ if err != nil { | |
+ log.Errorf("Error creating Bgp neighbor {%+v}. Err: %v", bgpNeighborCfg.Neighbor, err) | |
+ return err | |
+ } | |
+ return nil | |
+} | |
+ | |
+//BgpDelete deletes bgp neighbor | |
+func (ac *APIController) BgpDelete(bgpNeighborCfg *contivModel.Bgp) error { | |
+ | |
+ log.Infof("Received delete for Bgp config on {%+v} ", bgpNeighborCfg.Name) | |
+ // Get the state driver | |
+ stateDriver, err := utils.GetStateDriver() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ err = master.DeleteBgpNeighbors(stateDriver, bgpNeighborCfg.Name) | |
+ if err != nil { | |
+ log.Errorf("Error Deleting Bgp neighbor. Err: %v", err) | |
+ | |
+ return err | |
+ } | |
+ return nil | |
+} | |
+ | |
+//BgpUpdate updates bgp config | |
+func (ac *APIController) BgpUpdate(oldbgpNeighborCfg *contivModel.Bgp, NewbgpNeighborCfg *contivModel.Bgp) error { | |
+ return nil | |
+} | |
diff --git a/netmaster/objApi/infraproxy.go b/netmaster/objApi/infraproxy.go | |
old mode 100644 | |
new mode 100755 | |
diff --git a/netplugin/cluster/cluster.go b/netplugin/cluster/cluster.go | |
old mode 100644 | |
new mode 100755 | |
index 93d5355..5903cbb | |
--- a/netplugin/cluster/cluster.go | |
+++ b/netplugin/cluster/cluster.go | |
@@ -127,7 +127,7 @@ func registerService(objdbClient objdb.ObjdbApi, localIP string) error { | |
srvInfo := objdb.ServiceInfo{ | |
ServiceName: "netplugin", | |
HostAddr: localIP, | |
- Port: ofnet.OFNET_AGENT_PORT, | |
+ Port: ofnet.OFNET_AGENT_VXLAN_PORT, | |
} | |
// Register the node with service registry | |
@@ -178,7 +178,15 @@ func peerDiscoveryLoop(netplugin *plugin.NetPlugin, objdbClient objdb.ObjdbApi, | |
// add the node | |
err := netplugin.AddPeerHost(core.ServiceInfo{ | |
HostAddr: node.HostAddr, | |
- Port: ofnet.OFNET_AGENT_PORT, | |
+ Port: ofnet.OFNET_AGENT_VXLAN_PORT, | |
+ }) | |
+ if err != nil { | |
+ log.Errorf("Error adding node {%+v}. Err: %v", node, err) | |
+ } | |
+ // add the node | |
+ err = netplugin.AddPeerHost(core.ServiceInfo{ | |
+ HostAddr: node.HostAddr, | |
+ Port: ofnet.OFNET_AGENT_VLAN_PORT, | |
}) | |
if err != nil { | |
log.Errorf("Error adding node {%+v}. Err: %v", node, err) | |
@@ -225,18 +233,35 @@ func peerDiscoveryLoop(netplugin *plugin.NetPlugin, objdbClient objdb.ObjdbApi, | |
// add the node | |
err := netplugin.AddPeerHost(core.ServiceInfo{ | |
HostAddr: nodeInfo.HostAddr, | |
- Port: ofnet.OFNET_AGENT_PORT, | |
+ Port: ofnet.OFNET_AGENT_VXLAN_PORT, | |
}) | |
if err != nil { | |
log.Errorf("Error adding node {%+v}. Err: %v", nodeInfo, err) | |
} | |
+ // add the node | |
+ err = netplugin.AddPeerHost(core.ServiceInfo{ | |
+ HostAddr: nodeInfo.HostAddr, | |
+ Port: ofnet.OFNET_AGENT_VLAN_PORT, | |
+ }) | |
+ if err != nil { | |
+ log.Errorf("Error adding node {%+v}. Err: %v", nodeInfo, err) | |
+ } | |
+ | |
} else if srvEvent.EventType == objdb.WatchServiceEventDel { | |
log.Infof("Node delete event for {%+v}", nodeInfo) | |
// remove the node | |
err := netplugin.DeletePeerHost(core.ServiceInfo{ | |
HostAddr: nodeInfo.HostAddr, | |
- Port: ofnet.OFNET_AGENT_PORT, | |
+ Port: ofnet.OFNET_AGENT_VXLAN_PORT, | |
+ }) | |
+ if err != nil { | |
+ log.Errorf("Error adding node {%+v}. Err: %v", nodeInfo, err) | |
+ } | |
+ // remove the node | |
+ err = netplugin.DeletePeerHost(core.ServiceInfo{ | |
+ HostAddr: nodeInfo.HostAddr, | |
+ Port: ofnet.OFNET_AGENT_VLAN_PORT, | |
}) | |
if err != nil { | |
log.Errorf("Error adding node {%+v}. Err: %v", nodeInfo, err) | |
diff --git a/netplugin/netd.go b/netplugin/netd.go | |
old mode 100644 | |
new mode 100755 | |
index 53e6f94..6ea04e7 | |
--- a/netplugin/netd.go | |
+++ b/netplugin/netd.go | |
@@ -52,6 +52,8 @@ type cliOpts struct { | |
ctrlIP string // IP address to be used by control protocols | |
vtepIP string // IP address to be used by the VTEP | |
vlanIntf string // Uplink interface for VLAN switching | |
+ routerIP string // myrouter ip to start a protocol like Bgp | |
+ fwdMode string // default "bridge". Values: "routing" , "bridge" | |
} | |
func skipHost(vtepIP, homingHost, myHostLabel string) bool { | |
@@ -82,6 +84,17 @@ func processCurrentState(netPlugin *plugin.NetPlugin, opts cliOpts) error { | |
} | |
} | |
+ readBgp := &mastercfg.CfgBgpState{} | |
+ readBgp.StateDriver = netPlugin.StateDriver | |
+ bgpCfgs, err := readBgp.ReadAll() | |
+ if err == nil { | |
+ for idx, bgpCfg := range bgpCfgs { | |
+ bgp := bgpCfg.(*mastercfg.CfgBgpState) | |
+ log.Debugf("read bgp key[%d] %s, populating state \n", idx, bgp.Name) | |
+ processBgpEvent(netPlugin, opts, bgp.Name, false) | |
+ } | |
+ } | |
+ | |
return nil | |
} | |
@@ -96,7 +109,7 @@ func processNetEvent(netPlugin *plugin.NetPlugin, nwCfg *mastercfg.CfgNetworkSta | |
operStr := "" | |
if isDelete { | |
- err = netPlugin.DeleteNetwork(nwCfg.ID, nwCfg.PktTagType, nwCfg.PktTag, nwCfg.ExtPktTag) | |
+ err = netPlugin.DeleteNetwork(nwCfg.ID, nwCfg.PktTagType, nwCfg.PktTag, nwCfg.ExtPktTag, nwCfg.Gateway) | |
operStr = "delete" | |
} else { | |
err = netPlugin.CreateNetwork(nwCfg.ID) | |
@@ -124,11 +137,11 @@ func processEpState(netPlugin *plugin.NetPlugin, opts cliOpts, epID string) erro | |
epCfg := &mastercfg.CfgEndpointState{} | |
epCfg.StateDriver = netPlugin.StateDriver | |
err := epCfg.Read(epID) | |
+ | |
if err != nil { | |
log.Errorf("Failed to read config for ep '%s' \n", epID) | |
return err | |
} | |
- | |
// if the endpoint is not for this host, ignore it | |
if skipHost(epCfg.VtepIP, epCfg.HomingHost, opts.hostLabel) { | |
log.Infof("skipping mismatching host for ep %s. EP's host %s (my host: %s)", | |
@@ -167,11 +180,14 @@ func processStateEvent(netPlugin *plugin.NetPlugin, opts cliOpts, rsps chan core | |
// by just triggering create once instead. | |
log.Debugf("Received a modify event, treating it as a 'create'") | |
} | |
- | |
if nwCfg, ok := currentState.(*mastercfg.CfgNetworkState); ok { | |
log.Infof("Received %q for network: %q", eventStr, nwCfg.ID) | |
processNetEvent(netPlugin, nwCfg, isDelete) | |
} | |
+ if bgpCfg, ok := currentState.(*mastercfg.CfgBgpState); ok { | |
+ log.Infof("Received %q for Bgp: %q", eventStr, bgpCfg.Name) | |
+ processBgpEvent(netPlugin, opts, bgpCfg.Name, isDelete) | |
+ } | |
} | |
} | |
@@ -184,10 +200,23 @@ func handleNetworkEvents(netPlugin *plugin.NetPlugin, opts cliOpts, retErr chan | |
return | |
} | |
+func handleBgpEvents(netPlugin *plugin.NetPlugin, opts cliOpts, recvErr chan error) { | |
+ | |
+ rsps := make(chan core.WatchState) | |
+ go processStateEvent(netPlugin, opts, rsps) | |
+ cfg := mastercfg.CfgBgpState{} | |
+ cfg.StateDriver = netPlugin.StateDriver | |
+ recvErr <- cfg.WatchAll(rsps) | |
+ return | |
+} | |
+ | |
func handleEvents(netPlugin *plugin.NetPlugin, opts cliOpts) error { | |
+ | |
recvErr := make(chan error, 1) | |
go handleNetworkEvents(netPlugin, opts, recvErr) | |
+ go handleBgpEvents(netPlugin, opts, recvErr) | |
+ | |
err := <-recvErr | |
if err != nil { | |
log.Errorf("Failure occured. Error: %s", err) | |
@@ -285,6 +314,14 @@ func main() { | |
"vlan-if", | |
defVlanIntf, | |
"My VTEP ip address") | |
+ flagSet.StringVar(&opts.routerIP, | |
+ "router-ip", | |
+ "", | |
+ "My Router ip address") | |
+ flagSet.StringVar(&opts.fwdMode, | |
+ "fwd-mode", | |
+ "bridge", | |
+ "Forwarding Mode") | |
err = flagSet.Parse(os.Args[1:]) | |
if err != nil { | |
@@ -310,6 +347,11 @@ func main() { | |
configureSyslog(opts.syslog) | |
} | |
+ if opts.fwdMode != "bridge" && opts.fwdMode != "routing" { | |
+ log.Infof("Invalid forwarding mode. Setting the mode to bridge ") | |
+ opts.fwdMode = "bridge" | |
+ } | |
+ | |
if flagSet.NFlag() < 1 { | |
log.Infof("host-label not specified, using default (%s)", opts.hostLabel) | |
} | |
@@ -322,7 +364,9 @@ func main() { | |
"plugin-instance": { | |
"host-label": %q, | |
"vtep-ip": %q, | |
- "vlan-if": %q | |
+ "vlan-if": %q, | |
+ "router-ip":%q, | |
+ "fwdMode":%q | |
}, | |
%q : { | |
"dbip": "127.0.0.1", | |
@@ -335,7 +379,7 @@ func main() { | |
"socket" : "unix:///var/run/docker.sock" | |
} | |
}`, utils.OvsNameStr, opts.hostLabel, opts.vtepIP, | |
- opts.vlanIntf, utils.OvsNameStr) | |
+ opts.vlanIntf, opts.routerIP, opts.fwdMode, utils.OvsNameStr) | |
netPlugin := &plugin.NetPlugin{} | |
@@ -376,6 +420,12 @@ func main() { | |
if pluginConfig.Instance.VlanIntf == "" { | |
pluginConfig.Instance.VlanIntf = opts.vlanIntf | |
} | |
+ if pluginConfig.Instance.RouterIP == "" { | |
+ pluginConfig.Instance.RouterIP = opts.routerIP | |
+ } | |
+ if pluginConfig.Instance.FwdMode == "" { | |
+ pluginConfig.Instance.FwdMode = opts.fwdMode | |
+ } | |
// Initialize appropriate plugin | |
switch opts.pluginMode { | |
@@ -408,3 +458,31 @@ func main() { | |
os.Exit(1) | |
} | |
} | |
+ | |
+//processBgpEvent processes Bgp neighbor add/delete events | |
+func processBgpEvent(netPlugin *plugin.NetPlugin, opts cliOpts, hostID string, | |
+ isDelete bool) (err error) { | |
+ | |
+ if opts.hostLabel != hostID { | |
+ log.Errorf("Skipping deleting neighbor on this host") | |
+ return | |
+ } | |
+ | |
+ netPlugin.Lock() | |
+ defer func() { netPlugin.Unlock() }() | |
+ | |
+ operStr := "" | |
+ if isDelete { | |
+ err = netPlugin.DeleteBgpNeighbors(hostID) | |
+ operStr = "delete" | |
+ } else { | |
+ err = netPlugin.AddBgpNeighbors(hostID) | |
+ operStr = "create" | |
+ } | |
+ if err != nil { | |
+ log.Errorf("Bgp operation %s failed. Error: %s", operStr, err) | |
+ } else { | |
+ log.Infof("Bgp operation %s succeeded", operStr) | |
+ } | |
+ return | |
+} | |
diff --git a/netplugin/plugin/netplugin.go b/netplugin/plugin/netplugin.go | |
old mode 100644 | |
new mode 100755 | |
index aefe535..679234d | |
--- a/netplugin/plugin/netplugin.go | |
+++ b/netplugin/plugin/netplugin.go | |
@@ -66,6 +66,8 @@ func (p *NetPlugin) Init(pluginConfig Config, configStr string) error { | |
HostLabel: pluginConfig.Instance.HostLabel, | |
VtepIP: pluginConfig.Instance.VtepIP, | |
VlanIntf: pluginConfig.Instance.VlanIntf, | |
+ RouterIP: pluginConfig.Instance.RouterIP, | |
+ FwdMode: pluginConfig.Instance.FwdMode, | |
StateDriver: p.StateDriver, | |
} | |
@@ -102,8 +104,8 @@ func (p *NetPlugin) CreateNetwork(id string) error { | |
} | |
// DeleteNetwork deletes a network provided by the ID. | |
-func (p *NetPlugin) DeleteNetwork(id, encap string, pktTag, extPktTag int) error { | |
- return p.NetworkDriver.DeleteNetwork(id, encap, pktTag, extPktTag) | |
+func (p *NetPlugin) DeleteNetwork(id, encap string, pktTag, extPktTag int, Gw string) error { | |
+ return p.NetworkDriver.DeleteNetwork(id, encap, pktTag, extPktTag, Gw) | |
} | |
// FetchNetwork retrieves a network's state given an ID. | |
@@ -145,3 +147,13 @@ func (p *NetPlugin) AddMaster(node core.ServiceInfo) error { | |
func (p *NetPlugin) DeleteMaster(node core.ServiceInfo) error { | |
return p.NetworkDriver.DeleteMaster(node) | |
} | |
+ | |
+//AddBgpNeighbors adds bgp neigbor | |
+func (p *NetPlugin) AddBgpNeighbors(id string) error { | |
+ return p.NetworkDriver.AddBgpNeighbors(id) | |
+} | |
+ | |
+//DeleteBgpNeighbors deletes bgp neigbor | |
+func (p *NetPlugin) DeleteBgpNeighbors(id string) error { | |
+ return p.NetworkDriver.DeleteBgpNeighbors(id) | |
+} | |
diff --git a/netplugin/plugin/netplugin_test.go b/netplugin/plugin/netplugin_test.go | |
old mode 100644 | |
new mode 100755 | |
index 5357b47..ffe3f3b | |
--- a/netplugin/plugin/netplugin_test.go | |
+++ b/netplugin/plugin/netplugin_test.go | |
@@ -33,7 +33,8 @@ func TestNetPluginInit(t *testing.T) { | |
"container": "docker" | |
}, | |
"plugin-instance": { | |
- "host-label": "testHost" | |
+ "host-label": "testHost", | |
+ "fwd-mode":"bridge" | |
}, | |
"ovs" : { | |
"dbip": "127.0.0.1", | |
@@ -146,7 +147,8 @@ func TestNetPluginInitInvalidConfigMissingStateDriverName(t *testing.T) { | |
"container": "docker" | |
}, | |
"plugin-instance": { | |
- "host-label": "testHost" | |
+ "host-label": "testHost", | |
+ "fwd-mode":"bridge" | |
}, | |
"ovs" : { | |
"dbip": "127.0.0.1", | |
@@ -184,7 +186,8 @@ func TestNetPluginInitInvalidConfigMissingStateDriver(t *testing.T) { | |
"container": "docker" | |
}, | |
"plugin-instance": { | |
- "host-label": "testHost" | |
+ "host-label": "testHost", | |
+ "fwd-mode":"bridge" | |
}, | |
"ovs" : { | |
"dbip": "127.0.0.1", | |
@@ -218,7 +221,8 @@ func TestNetPluginInitInvalidConfigMissingNetworkDriverName(t *testing.T) { | |
"container": "docker" | |
}, | |
"plugin-instance": { | |
- "host-label": "testHost" | |
+ "host-label": "testHost", | |
+ "fwd-mode":"bridge" | |
}, | |
"ovs" : { | |
"dbip": "127.0.0.1", | |
@@ -254,7 +258,8 @@ func TestNetPluginInitInvalidConfigMissingNetworkDriver(t *testing.T) { | |
"container": "docker" | |
}, | |
"plugin-instance": { | |
- "host-label": "testHost" | |
+ "host-label": "testHost", | |
+ "fwd-mode":"bridge" | |
}, | |
"fakedriver" : { | |
}, | |
@@ -277,3 +282,36 @@ func TestNetPluginInitInvalidConfigMissingNetworkDriver(t *testing.T) { | |
} | |
defer func() { plugin.Deinit() }() | |
} | |
+ | |
+func TestNetPluginInitInvalidConfigMissingFwdMode(t *testing.T) { | |
+ configStr := `{ | |
+ "drivers" : { | |
+ "network": "ovs", | |
+ "endpoint": "ovs", | |
+ "state": "fakedriver", | |
+ "container": "docker", | |
+ }, | |
+ "plugin-instance": { | |
+ "host-label": "testHost" | |
+ }, | |
+ "ovs" : { | |
+ "dbip": "127.0.0.1", | |
+ "dbport": 6640 | |
+ }, | |
+ "fakedriver" : { | |
+ }, | |
+ "docker" : { | |
+ "socket" : "unix:///var/run/docker.sock" | |
+ } | |
+ }` | |
+ | |
+ // Parse the config | |
+ pluginConfig := Config{} | |
+ err := json.Unmarshal([]byte(configStr), &pluginConfig) | |
+ | |
+ plugin := NetPlugin{} | |
+ err = plugin.Init(pluginConfig, configStr) | |
+ if err == nil { | |
+ t.Fatalf("plugin init succeeded, should have failed!") | |
+ } | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment