@@ -21,6 +21,7 @@ import (
21
21
"net"
22
22
"os"
23
23
"runtime"
24
+ "sort"
24
25
"syscall"
25
26
"time"
26
27
@@ -46,18 +47,19 @@ const defaultBrName = "cni0"
46
47
47
48
type NetConf struct {
48
49
types.NetConf
49
- BrName string `json:"bridge"`
50
- IsGW bool `json:"isGateway"`
51
- IsDefaultGW bool `json:"isDefaultGateway"`
52
- ForceAddress bool `json:"forceAddress"`
53
- IPMasq bool `json:"ipMasq"`
54
- MTU int `json:"mtu"`
55
- HairpinMode bool `json:"hairpinMode"`
56
- PromiscMode bool `json:"promiscMode"`
57
- Vlan int `json:"vlan"`
58
- PreserveDefaultVlan bool `json:"preserveDefaultVlan"`
59
- MacSpoofChk bool `json:"macspoofchk,omitempty"`
60
- EnableDad bool `json:"enabledad,omitempty"`
50
+ BrName string `json:"bridge"`
51
+ IsGW bool `json:"isGateway"`
52
+ IsDefaultGW bool `json:"isDefaultGateway"`
53
+ ForceAddress bool `json:"forceAddress"`
54
+ IPMasq bool `json:"ipMasq"`
55
+ MTU int `json:"mtu"`
56
+ HairpinMode bool `json:"hairpinMode"`
57
+ PromiscMode bool `json:"promiscMode"`
58
+ Vlan int `json:"vlan"`
59
+ VlanTrunk []* VlanTrunk `json:"vlanTrunk,omitempty"`
60
+ PreserveDefaultVlan bool `json:"preserveDefaultVlan"`
61
+ MacSpoofChk bool `json:"macspoofchk,omitempty"`
62
+ EnableDad bool `json:"enabledad,omitempty"`
61
63
62
64
Args struct {
63
65
Cni BridgeArgs `json:"cni,omitempty"`
@@ -66,7 +68,14 @@ type NetConf struct {
66
68
Mac string `json:"mac,omitempty"`
67
69
} `json:"runtimeConfig,omitempty"`
68
70
69
- mac string
71
+ mac string
72
+ vlans []int
73
+ }
74
+
75
+ type VlanTrunk struct {
76
+ MinID * int `json:"minID,omitempty"`
77
+ MaxID * int `json:"maxID,omitempty"`
78
+ ID * int `json:"id,omitempty"`
70
79
}
71
80
72
81
type BridgeArgs struct {
@@ -104,6 +113,12 @@ func loadNetConf(bytes []byte, envArgs string) (*NetConf, string, error) {
104
113
if n .Vlan < 0 || n .Vlan > 4094 {
105
114
return nil , "" , fmt .Errorf ("invalid VLAN ID %d (must be between 0 and 4094)" , n .Vlan )
106
115
}
116
+ var err error
117
+ n .vlans , err = collectVlanTrunk (n .VlanTrunk )
118
+ if err != nil {
119
+ // fail to parsing
120
+ return nil , "" , err
121
+ }
107
122
108
123
if envArgs != "" {
109
124
e := MacEnvArgs {}
@@ -127,6 +142,59 @@ func loadNetConf(bytes []byte, envArgs string) (*NetConf, string, error) {
127
142
return n , n .CNIVersion , nil
128
143
}
129
144
145
+ // This method is copied from https://github.com/k8snetworkplumbingwg/ovs-cni/blob/v0.27.2/pkg/plugin/plugin.go
146
+ func collectVlanTrunk (vlanTrunk []* VlanTrunk ) ([]int , error ) {
147
+ if vlanTrunk == nil {
148
+ return nil , nil
149
+ }
150
+
151
+ vlanMap := make (map [int ]bool )
152
+ for _ , item := range vlanTrunk {
153
+ var minID int
154
+ var maxID int
155
+ var ID int
156
+ if item .MinID != nil {
157
+ minID = * item .MinID
158
+ if minID < 0 || minID > 4094 {
159
+ return nil , errors .New ("incorrect trunk minID parameter" )
160
+ }
161
+ }
162
+ if item .MaxID != nil {
163
+ maxID = * item .MaxID
164
+ if maxID < 0 || maxID > 4094 {
165
+ return nil , errors .New ("incorrect trunk maxID parameter" )
166
+ }
167
+ if maxID < minID {
168
+ return nil , errors .New ("minID is greater than maxID in trunk parameter" )
169
+ }
170
+ }
171
+ if minID > 0 && maxID > 0 {
172
+ for v := minID ; v <= maxID ; v ++ {
173
+ vlanMap [v ] = true
174
+ }
175
+ }
176
+
177
+ // single vid
178
+ if item .ID != nil {
179
+ ID = * item .ID
180
+ if ID < 0 || ID > 4094 {
181
+ return nil , errors .New ("incorrect trunk id parameter" )
182
+ }
183
+ vlanMap [ID ] = true
184
+ }
185
+ }
186
+
187
+ if len (vlanMap ) == 0 {
188
+ return nil , nil
189
+ }
190
+ vlans := make ([]int , 0 , len (vlanMap ))
191
+ for k := range vlanMap {
192
+ vlans = append (vlans , k )
193
+ }
194
+ sort .Slice (vlans , func (i int , j int ) bool { return vlans [i ] < vlans [j ] })
195
+ return vlans , nil
196
+ }
197
+
130
198
// calcGateways processes the results from the IPAM plugin and does the
131
199
// following for each IP family:
132
200
// - Calculates and compiles a list of gateway addresses
@@ -316,7 +384,7 @@ func ensureVlanInterface(br *netlink.Bridge, vlanID int, preserveDefaultVlan boo
316
384
return nil , fmt .Errorf ("faild to find host namespace: %v" , err )
317
385
}
318
386
319
- _ , brGatewayIface , err := setupVeth (hostNS , br , name , br .MTU , false , vlanID , preserveDefaultVlan , "" )
387
+ _ , brGatewayIface , err := setupVeth (hostNS , br , name , br .MTU , false , vlanID , nil , preserveDefaultVlan , "" )
320
388
if err != nil {
321
389
return nil , fmt .Errorf ("faild to create vlan gateway %q: %v" , name , err )
322
390
}
@@ -335,7 +403,7 @@ func ensureVlanInterface(br *netlink.Bridge, vlanID int, preserveDefaultVlan boo
335
403
return brGatewayVeth , nil
336
404
}
337
405
338
- func setupVeth (netns ns.NetNS , br * netlink.Bridge , ifName string , mtu int , hairpinMode bool , vlanID int , preserveDefaultVlan bool , mac string ) (* current.Interface , * current.Interface , error ) {
406
+ func setupVeth (netns ns.NetNS , br * netlink.Bridge , ifName string , mtu int , hairpinMode bool , vlanID int , vlans [] int , preserveDefaultVlan bool , mac string ) (* current.Interface , * current.Interface , error ) {
339
407
contIface := & current.Interface {}
340
408
hostIface := & current.Interface {}
341
409
@@ -386,6 +454,14 @@ func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairp
386
454
}
387
455
}
388
456
457
+ // S1031: unnecessary nil check around range (gosimple)
458
+ for _ , v := range vlans {
459
+ err = netlink .BridgeVlanAdd (hostVeth , uint16 (v ), false , false , false , true )
460
+ if err != nil {
461
+ return nil , nil , fmt .Errorf ("failed to setup vlan tag on interface %q: %w" , hostIface .Name , err )
462
+ }
463
+ }
464
+
389
465
return hostIface , contIface , nil
390
466
}
391
467
@@ -414,7 +490,10 @@ func calcGatewayIP(ipn *net.IPNet) net.IP {
414
490
}
415
491
416
492
func setupBridge (n * NetConf ) (* netlink.Bridge , * current.Interface , error ) {
417
- vlanFiltering := n .Vlan != 0
493
+ vlanFiltering := false
494
+ if n .Vlan != 0 || n .VlanTrunk != nil {
495
+ vlanFiltering = true
496
+ }
418
497
// create bridge if necessary
419
498
br , err := ensureBridge (n .BrName , n .MTU , n .PromiscMode , vlanFiltering )
420
499
if err != nil {
@@ -452,6 +531,10 @@ func cmdAdd(args *skel.CmdArgs) error {
452
531
return fmt .Errorf ("cannot set hairpin mode and promiscuous mode at the same time" )
453
532
}
454
533
534
+ if n .vlans != nil && len (n .vlans ) > 0 && isLayer3 {
535
+ return fmt .Errorf ("cannot set vlanTrunk and IPAM at the same time" )
536
+ }
537
+
455
538
br , brInterface , err := setupBridge (n )
456
539
if err != nil {
457
540
return err
@@ -463,7 +546,7 @@ func cmdAdd(args *skel.CmdArgs) error {
463
546
}
464
547
defer netns .Close ()
465
548
466
- hostInterface , containerInterface , err := setupVeth (netns , br , args .IfName , n .MTU , n .HairpinMode , n .Vlan , n .PreserveDefaultVlan , n .mac )
549
+ hostInterface , containerInterface , err := setupVeth (netns , br , args .IfName , n .MTU , n .HairpinMode , n .Vlan , n .vlans , n . PreserveDefaultVlan , n .mac )
467
550
if err != nil {
468
551
return err
469
552
}
0 commit comments