Merge pull request #195 from SchSeba/l2-bridge
L2 bridge Implementation
This commit is contained in:
commit
3fb464786f
@ -28,6 +28,17 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example L2-only configuration
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"name": "mynet",
|
||||||
|
"type": "bridge",
|
||||||
|
"bridge": "mynet0",
|
||||||
|
"ipam": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Network configuration reference
|
## Network configuration reference
|
||||||
|
|
||||||
* `name` (string, required): the name of the network.
|
* `name` (string, required): the name of the network.
|
||||||
@ -39,5 +50,5 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa
|
|||||||
* `ipMasq` (boolean, optional): set up IP Masquerade on the host for traffic originating from this network and destined outside of it. Defaults to false.
|
* `ipMasq` (boolean, optional): set up IP Masquerade on the host for traffic originating from this network and destined outside of it. Defaults to false.
|
||||||
* `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel.
|
* `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel.
|
||||||
* `hairpinMode` (boolean, optional): set hairpin mode for interfaces on the bridge. Defaults to false.
|
* `hairpinMode` (boolean, optional): set hairpin mode for interfaces on the bridge. Defaults to false.
|
||||||
* `ipam` (dictionary, required): IPAM configuration to be used for this network.
|
* `ipam` (dictionary, required): IPAM configuration to be used for this network. For L2-only network, create empty dictionary.
|
||||||
* `promiscMode` (boolean, optional): set promiscuous mode on the bridge. Defaults to false.
|
* `promiscMode` (boolean, optional): set promiscuous mode on the bridge. Defaults to false.
|
||||||
|
@ -334,6 +334,8 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLayer3 := n.IPAM.Type != ""
|
||||||
|
|
||||||
if n.IsDefaultGW {
|
if n.IsDefaultGW {
|
||||||
n.IsGW = true
|
n.IsGW = true
|
||||||
}
|
}
|
||||||
@ -358,6 +360,10 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assume L2 interface only
|
||||||
|
result := ¤t.Result{CNIVersion: cniVersion, Interfaces: []*current.Interface{brInterface, hostInterface, containerInterface}}
|
||||||
|
|
||||||
|
if isLayer3 {
|
||||||
// run the IPAM plugin and get back the config to apply
|
// run the IPAM plugin and get back the config to apply
|
||||||
r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)
|
r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -374,17 +380,18 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Convert whatever the IPAM result was into the current Result type
|
// Convert whatever the IPAM result was into the current Result type
|
||||||
result, err := current.NewResultFromResult(r)
|
ipamResult, err := current.NewResultFromResult(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.IPs = ipamResult.IPs
|
||||||
|
result.Routes = ipamResult.Routes
|
||||||
|
|
||||||
if len(result.IPs) == 0 {
|
if len(result.IPs) == 0 {
|
||||||
return errors.New("IPAM plugin returned missing IP config")
|
return errors.New("IPAM plugin returned missing IP config")
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Interfaces = []*current.Interface{brInterface, hostInterface, containerInterface}
|
|
||||||
|
|
||||||
// Gather gateway information for each IP family
|
// Gather gateway information for each IP family
|
||||||
gwsV4, gwsV6, err := calcGateways(result, n)
|
gwsV4, gwsV6, err := calcGateways(result, n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -458,6 +465,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Refetch the bridge since its MAC address may change when the first
|
// Refetch the bridge since its MAC address may change when the first
|
||||||
// veth is added or after its IP address is set
|
// veth is added or after its IP address is set
|
||||||
@ -485,9 +493,13 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLayer3 := n.IPAM.Type != ""
|
||||||
|
|
||||||
|
if isLayer3 {
|
||||||
if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil {
|
if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if args.Netns == "" {
|
if args.Netns == "" {
|
||||||
return nil
|
return nil
|
||||||
@ -510,7 +522,7 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.IPMasq {
|
if isLayer3 && n.IPMasq {
|
||||||
chain := utils.FormatChainName(n.Name, args.ContainerID)
|
chain := utils.FormatChainName(n.Name, args.ContainerID)
|
||||||
comment := utils.FormatComment(n.Name, args.ContainerID)
|
comment := utils.FormatComment(n.Name, args.ContainerID)
|
||||||
for _, ipn := range ipnets {
|
for _, ipn := range ipnets {
|
||||||
|
@ -47,6 +47,7 @@ type testCase struct {
|
|||||||
gateway string // Single subnet config: Gateway
|
gateway string // Single subnet config: Gateway
|
||||||
ranges []rangeInfo // Ranges list (multiple subnets config)
|
ranges []rangeInfo // Ranges list (multiple subnets config)
|
||||||
isGW bool
|
isGW bool
|
||||||
|
isLayer2 bool
|
||||||
expGWCIDRs []string // Expected gateway addresses in CIDR form
|
expGWCIDRs []string // Expected gateway addresses in CIDR form
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +78,9 @@ const (
|
|||||||
"cniVersion": "%s",
|
"cniVersion": "%s",
|
||||||
"name": "testConfig",
|
"name": "testConfig",
|
||||||
"type": "bridge",
|
"type": "bridge",
|
||||||
"bridge": "%s",
|
"bridge": "%s",`
|
||||||
|
|
||||||
|
netDefault = `
|
||||||
"isDefaultGateway": true,
|
"isDefaultGateway": true,
|
||||||
"ipMasq": false`
|
"ipMasq": false`
|
||||||
|
|
||||||
@ -117,6 +120,8 @@ const (
|
|||||||
// for a test case.
|
// for a test case.
|
||||||
func (tc testCase) netConfJSON(dataDir string) string {
|
func (tc testCase) netConfJSON(dataDir string) string {
|
||||||
conf := fmt.Sprintf(netConfStr, tc.cniVersion, BRNAME)
|
conf := fmt.Sprintf(netConfStr, tc.cniVersion, BRNAME)
|
||||||
|
if !tc.isLayer2 {
|
||||||
|
conf += netDefault
|
||||||
if tc.subnet != "" || tc.ranges != nil {
|
if tc.subnet != "" || tc.ranges != nil {
|
||||||
conf += ipamStartStr
|
conf += ipamStartStr
|
||||||
if dataDir != "" {
|
if dataDir != "" {
|
||||||
@ -130,6 +135,10 @@ func (tc testCase) netConfJSON(dataDir string) string {
|
|||||||
}
|
}
|
||||||
conf += ipamEndStr
|
conf += ipamEndStr
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
conf += `
|
||||||
|
"ipam": {}`
|
||||||
|
}
|
||||||
return "{" + conf + "\n}"
|
return "{" + conf + "\n}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +345,10 @@ func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) {
|
|||||||
// Check that the bridge has a different mac from the veth
|
// Check that the bridge has a different mac from the veth
|
||||||
// If not, it means the bridge has an unstable mac and will change
|
// If not, it means the bridge has an unstable mac and will change
|
||||||
// as ifs are added and removed
|
// as ifs are added and removed
|
||||||
|
// this check is not relevant for a layer 2 bridge
|
||||||
|
if !tc.isLayer2 {
|
||||||
Expect(link.Attrs().HardwareAddr.String()).NotTo(Equal(bridgeMAC))
|
Expect(link.Attrs().HardwareAddr.String()).NotTo(Equal(bridgeMAC))
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -700,6 +712,16 @@ var _ = Describe("bridge Operations", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures a l2 bridge and veth with ADD/DEL for 0.3.1 config", func() {
|
||||||
|
tc := testCase{cniVersion: "0.3.0", isLayer2: true}
|
||||||
|
cmdAddDelTest(originalNS, tc, dataDir)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures a l2 bridge and veth with ADD/DEL for 0.3.1 config", func() {
|
||||||
|
tc := testCase{cniVersion: "0.3.1", isLayer2: true}
|
||||||
|
cmdAddDelTest(originalNS, tc, dataDir)
|
||||||
|
})
|
||||||
|
|
||||||
It("configures and deconfigures a bridge and veth with default route with ADD/DEL for 0.3.1 config", func() {
|
It("configures and deconfigures a bridge and veth with default route with ADD/DEL for 0.3.1 config", func() {
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user