9 "go.fd.io/govpp/binapi/ethernet_types"
10 "go.fd.io/govpp/binapi/interface_types"
11 "go.fd.io/govpp/binapi/ip_types"
15 AddressWithPrefix = ip_types.AddressWithPrefix
16 MacAddress = ethernet_types.MacAddress
19 Configure func() error
23 NetTopology []NetConfig
25 NetConfigBase struct {
27 category string // what else to call this when `type` is reserved?
30 NetworkInterfaceVeth struct {
32 index interface_types.InterfaceIndex
33 peerNetworkNamespace string
36 ip4Address ip_types.AddressWithPrefix
37 hwAddress ethernet_types.MacAddress
40 NetworkInterfaceTap struct {
42 index interface_types.InterfaceIndex
46 NetworkNamespace struct {
50 NetworkBridge struct {
52 networkNamespace string
58 NetNs string = "netns"
61 Bridge string = "bridge"
64 func (b NetConfigBase) Name() string {
68 func (b NetConfigBase) Type() string {
72 func (iface NetworkInterfaceVeth) Configure() error {
73 err := AddVethPair(iface.name, iface.peerName)
78 if iface.peerNetworkNamespace != "" {
79 err := LinkSetNetns(iface.peerName, iface.peerNetworkNamespace)
85 if iface.peerIp4Address != "" {
86 err = AddAddress(iface.peerName, iface.peerIp4Address, iface.peerNetworkNamespace)
88 return fmt.Errorf("failed to add configure address for %s: %v", iface.peerName, err)
94 func (iface NetworkInterfaceVeth) Unconfigure() {
98 func (iface NetworkInterfaceVeth) Address() string {
99 return strings.Split(iface.ip4Address.String(), "/")[0]
102 func (iface NetworkInterfaceTap) Configure() error {
103 err := AddTap(iface.name, iface.ip4Address)
110 func (iface NetworkInterfaceTap) Unconfigure() {
114 func (ns NetworkNamespace) Configure() error {
115 return addDelNetns(ns.name, true)
118 func (ns NetworkNamespace) Unconfigure() {
119 addDelNetns(ns.name, false)
122 func (b NetworkBridge) Configure() error {
123 return AddBridge(b.name, b.interfaces, b.networkNamespace)
126 func (b NetworkBridge) Unconfigure() {
127 DelBridge(b.name, b.networkNamespace)
130 func (t *NetTopology) Configure() error {
131 for _, c := range *t {
140 func (t *NetTopology) Unconfigure() {
141 for _, c := range *t {
146 func newConfigFn(cfg NetDevConfig) func() error {
149 return func() error { return AddNetns(cfg["name"].(string)) }
150 } else if t == "veth" {
151 return func() error {
153 peer := cfg["peer"].(NetDevConfig)
154 peerName := peer["name"].(string)
155 err := AddVethPair(cfg["name"].(string), peerName)
160 if peer["netns"] != nil {
161 peerNs = peer["netns"].(string)
163 err := LinkSetNetns(peerName, peerNs)
169 if peer["ip4"] != nil {
170 err = AddAddress(peerName, peer["ip4"].(string), peerNs)
172 return fmt.Errorf("failed to add configure address for %s: %v", peerName, err)
177 } else if t == "bridge" {
178 return func() error { return configureBridge(cfg) }
179 } else if t == "tap" {
180 return func() error { return configureTap(cfg) }
185 func newUnconfigFn(cfg NetDevConfig) func() {
187 name := cfg["name"].(string)
190 return func() { DelLink(name) }
191 } else if t == "netns" {
192 return func() { DelNetns(name) }
193 } else if t == "veth" {
194 return func() { DelLink(name) }
195 } else if t == "bridge" {
196 return func() { DelBridge(name, cfg["netns"].(string)) }
201 func NewNetConfig(cfg NetDevConfig) NetConfig {
204 nc.Configure = newConfigFn(cfg)
205 nc.Unconfigure = newUnconfigFn(cfg)
210 func NewNetNamespace(cfg NetDevConfig) (NetworkNamespace, error) {
211 var networkNamespace NetworkNamespace
212 networkNamespace.name = cfg["name"].(string)
213 networkNamespace.category = "netns"
214 return networkNamespace, nil
217 func NewBridge(cfg NetDevConfig) (NetworkBridge, error) {
218 var bridge NetworkBridge
219 bridge.name = cfg["name"].(string)
220 bridge.category = "bridge"
221 for _, v := range cfg["interfaces"].([]interface{}) {
222 bridge.interfaces = append(bridge.interfaces, v.(string))
224 bridge.networkNamespace = cfg["netns"].(string)
228 func NewVeth(cfg NetDevConfig) (NetworkInterfaceVeth, error) {
229 var veth NetworkInterfaceVeth
231 veth.name = cfg["name"].(string)
232 veth.category = "veth"
234 if cfg["preset-hw-address"] != nil {
235 veth.hwAddress, err = ethernet_types.ParseMacAddress(cfg["preset-hw-address"].(string))
237 return NetworkInterfaceVeth{}, err
241 peer := cfg["peer"].(NetDevConfig)
243 veth.peerName = peer["name"].(string)
245 if peer["netns"] != nil {
246 veth.peerNetworkNamespace = peer["netns"].(string)
249 if peer["ip4"] != nil {
250 veth.peerIp4Address = peer["ip4"].(string)
256 func NewTap(cfg NetDevConfig) (NetworkInterfaceTap, error) {
257 var tap NetworkInterfaceTap
258 tap.name = cfg["name"].(string)
260 tap.ip4Address = cfg["ip4"].(string)
264 func DelBridge(brName, ns string) error {
265 err := SetDevDown(brName, ns)
270 err = addDelBridge(brName, ns, false)
278 func configureBridge(dev NetDevConfig) error {
280 for _, v := range dev["interfaces"].([]interface{}) {
281 ifs = append(ifs, v.(string))
283 return AddBridge(dev["name"].(string), ifs, dev["netns"].(string))
286 func configureTap(dev NetDevConfig) error {
287 return AddTap(dev["name"].(string), dev["ip4"].(string))
290 func SetDevUp(dev, ns string) error {
291 return setDevUpDown(dev, ns, true)
294 func SetDevDown(dev, ns string) error {
295 return setDevUpDown(dev, ns, false)
298 func AddTap(ifName, ifAddress string) error {
299 cmd := exec.Command("ip", "tuntap", "add", ifName, "mode", "tap")
300 o, err := cmd.CombinedOutput()
302 s := fmt.Sprintf("error creating tap %s: %v: %s", ifName, err, string(o))
306 cmd = exec.Command("ip", "addr", "add", ifAddress, "dev", ifName)
310 s := fmt.Sprintf("error setting addr for tap %s: %v", ifName, err)
314 err = SetDevUp(ifName, "")
322 func DelLink(ifName string) {
323 cmd := exec.Command("ip", "link", "del", ifName)
327 func setDevUpDown(dev, ns string, isUp bool) error {
334 c := []string{"ip", "link", "set", "dev", dev, op}
335 cmd := appendNetns(c, ns)
338 s := fmt.Sprintf("error bringing %s device %s!", dev, op)
344 func AddVethPair(ifName, peerName string) error {
345 cmd := exec.Command("ip", "link", "add", ifName, "type", "veth", "peer", "name", peerName)
348 return fmt.Errorf("creating veth pair failed: %v", err)
350 err = SetDevUp(ifName, "")
352 return fmt.Errorf("set link up failed: %v", err)
357 func addDelNetns(name string, isAdd bool) error {
364 cmd := exec.Command("ip", "netns", op, name)
365 _, err := cmd.CombinedOutput()
367 return errors.New("add/del netns failed")
372 func AddNetns(nsName string) error {
373 return addDelNetns(nsName, true)
376 func DelNetns(nsName string) error {
377 return addDelNetns(nsName, false)
380 func LinkSetNetns(ifName, ns string) error {
381 cmd := exec.Command("ip", "link", "set", "dev", ifName, "up", "netns", ns)
384 return fmt.Errorf("error setting device '%s' to netns '%s: %v", ifName, ns, err)
389 func NewCommand(s []string, ns string) *exec.Cmd {
390 return appendNetns(s, ns)
393 func appendNetns(s []string, ns string) *exec.Cmd {
396 // use default namespace
397 cmd = exec.Command(s[0], s[1:]...)
399 var args = []string{"netns", "exec", ns}
400 args = append(args, s[:]...)
401 cmd = exec.Command("ip", args...)
406 func addDelBridge(brName, ns string, isAdd bool) error {
413 var c = []string{"brctl", op, brName}
414 cmd := appendNetns(c, ns)
417 s := fmt.Sprintf("%s %s failed!", op, brName)
423 func AddBridge(brName string, ifs []string, ns string) error {
424 err := addDelBridge(brName, ns, true)
429 for _, v := range ifs {
430 c := []string{"brctl", "addif", brName, v}
431 cmd := appendNetns(c, ns)
434 s := fmt.Sprintf("error adding %s to bridge %s: %v", v, brName, err)
438 err = SetDevUp(brName, ns)