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 MacAddress = ethernet_types.MacAddress
16 AddressWithPrefix = ip_types.AddressWithPrefix
17 InterfaceIndex = interface_types.InterfaceIndex
19 LegacyNetConfig struct {
20 Configure func() error
24 NetTopology []LegacyNetConfig
33 NetConfigBase struct {
35 category string // what else to call this when `type` is reserved?
38 NetInterface interface {
41 Ip4AddressWithPrefix() AddressWithPrefix
42 Ip4AddressString() string
43 SetIndex(InterfaceIndex)
44 Index() InterfaceIndex
45 HwAddress() MacAddress
48 NetInterfaceBase struct {
51 ip4address string // this will have form 10.10.10.1/24
56 NetworkInterfaceVeth struct {
58 peerNetworkNamespace string
63 NetworkInterfaceTap struct {
67 NetworkNamespace struct {
71 NetworkBridge struct {
73 networkNamespace string
79 NetNs string = "netns"
82 Bridge string = "bridge"
85 func (b *NetConfigBase) Name() string {
89 func (b *NetConfigBase) Type() string {
93 func (b *NetInterfaceBase) SetAddress(address string) {
94 b.ip4address = address
97 func (b *NetInterfaceBase) SetIndex(index InterfaceIndex) {
101 func (b *NetInterfaceBase) Index() InterfaceIndex {
105 func (b *NetInterfaceBase) Ip4AddressWithPrefix() AddressWithPrefix {
106 address, _ := ip_types.ParseAddressWithPrefix(b.ip4address)
110 func (b *NetInterfaceBase) Ip4AddressString() string {
111 return strings.Split(b.ip4address, "/")[0]
114 func (b *NetInterfaceBase) HwAddress() MacAddress {
118 func (iface *NetworkInterfaceVeth) Configure() error {
119 err := AddVethPair(iface.name, iface.peerName)
124 if iface.peerNetworkNamespace != "" {
125 err := LinkSetNetns(iface.peerName, iface.peerNetworkNamespace)
131 if iface.peerIp4Address != "" {
132 err = AddAddress(iface.peerName, iface.peerIp4Address, iface.peerNetworkNamespace)
134 return fmt.Errorf("failed to add configure address for %s: %v", iface.peerName, err)
140 func (iface *NetworkInterfaceVeth) Unconfigure() {
144 func (iface *NetworkInterfaceVeth) PeerIp4AddressString() string {
145 return strings.Split(iface.peerIp4Address, "/")[0]
148 func (iface *NetworkInterfaceTap) Configure() error {
149 err := AddTap(iface.name, iface.Ip4AddressString())
156 func (iface *NetworkInterfaceTap) Unconfigure() {
160 func (ns *NetworkNamespace) Configure() error {
161 return addDelNetns(ns.name, true)
164 func (ns *NetworkNamespace) Unconfigure() {
165 addDelNetns(ns.name, false)
168 func (b *NetworkBridge) Configure() error {
169 return AddBridge(b.name, b.interfaces, b.networkNamespace)
172 func (b *NetworkBridge) Unconfigure() {
173 DelBridge(b.name, b.networkNamespace)
176 func (t *NetTopology) Configure() error {
177 for _, c := range *t {
186 func (t *NetTopology) Unconfigure() {
187 for _, c := range *t {
192 func newConfigFn(cfg NetDevConfig) func() error {
195 return func() error { return AddNetns(cfg["name"].(string)) }
196 } else if t == "veth" {
197 return func() error {
199 peer := cfg["peer"].(NetDevConfig)
200 peerName := peer["name"].(string)
201 err := AddVethPair(cfg["name"].(string), peerName)
206 if peer["netns"] != nil {
207 peerNs = peer["netns"].(string)
209 err := LinkSetNetns(peerName, peerNs)
215 if peer["ip4"] != nil {
216 err = AddAddress(peerName, peer["ip4"].(string), peerNs)
218 return fmt.Errorf("failed to add configure address for %s: %v", peerName, err)
223 } else if t == "bridge" {
224 return func() error { return configureBridge(cfg) }
229 func newUnconfigFn(cfg NetDevConfig) func() {
231 name := cfg["name"].(string)
234 return func() { DelNetns(name) }
235 } else if t == "veth" {
236 return func() { DelLink(name) }
237 } else if t == "bridge" {
238 return func() { DelBridge(name, cfg["netns"].(string)) }
243 func NewNetConfig(cfg NetDevConfig) LegacyNetConfig {
244 var nc LegacyNetConfig
246 nc.Configure = newConfigFn(cfg)
247 nc.Unconfigure = newUnconfigFn(cfg)
252 func NewNetNamespace(cfg NetDevConfig) (NetworkNamespace, error) {
253 var networkNamespace NetworkNamespace
254 networkNamespace.name = cfg["name"].(string)
255 networkNamespace.category = "netns"
256 return networkNamespace, nil
259 func NewBridge(cfg NetDevConfig) (NetworkBridge, error) {
260 var bridge NetworkBridge
261 bridge.name = cfg["name"].(string)
262 bridge.category = "bridge"
263 for _, v := range cfg["interfaces"].([]interface{}) {
264 bridge.interfaces = append(bridge.interfaces, v.(string))
266 bridge.networkNamespace = cfg["netns"].(string)
270 func NewVeth(cfg NetDevConfig, a *Addresser) (NetworkInterfaceVeth, error) {
271 var veth NetworkInterfaceVeth
274 veth.name = cfg["name"].(string)
275 veth.category = "veth"
277 if cfg["preset-hw-address"] != nil {
278 veth.hwAddress, err = ethernet_types.ParseMacAddress(cfg["preset-hw-address"].(string))
280 return NetworkInterfaceVeth{}, err
284 peer := cfg["peer"].(NetDevConfig)
286 veth.peerName = peer["name"].(string)
288 if peer["netns"] != nil {
289 veth.peerNetworkNamespace = peer["netns"].(string)
292 if peer["ip4"] != nil && peer["ip4"].(bool) == true {
293 veth.peerIp4Address, err = veth.addresser.
294 NewIp4AddressWithNamespace(veth.peerNetworkNamespace)
296 return NetworkInterfaceVeth{}, err
303 func NewTap(cfg NetDevConfig, a *Addresser) (NetworkInterfaceTap, error) {
304 var tap NetworkInterfaceTap
306 tap.name = cfg["name"].(string)
308 ip4Address, err := tap.addresser.NewIp4Address()
310 return NetworkInterfaceTap{}, err
312 tap.SetAddress(ip4Address)
316 func DelBridge(brName, ns string) error {
317 err := SetDevDown(brName, ns)
322 err = addDelBridge(brName, ns, false)
330 func configureBridge(dev NetDevConfig) error {
332 for _, v := range dev["interfaces"].([]interface{}) {
333 ifs = append(ifs, v.(string))
335 return AddBridge(dev["name"].(string), ifs, dev["netns"].(string))
338 func configureTap(dev NetDevConfig) error {
339 return AddTap(dev["name"].(string), dev["ip4"].(string))
342 func SetDevUp(dev, ns string) error {
343 return setDevUpDown(dev, ns, true)
346 func SetDevDown(dev, ns string) error {
347 return setDevUpDown(dev, ns, false)
350 func AddTap(ifName, ifAddress string) error {
351 cmd := exec.Command("ip", "tuntap", "add", ifName, "mode", "tap")
352 o, err := cmd.CombinedOutput()
354 s := fmt.Sprintf("error creating tap %s: %v: %s", ifName, err, string(o))
358 cmd = exec.Command("ip", "addr", "add", ifAddress, "dev", ifName)
362 s := fmt.Sprintf("error setting addr for tap %s: %v", ifName, err)
366 err = SetDevUp(ifName, "")
374 func DelLink(ifName string) {
375 cmd := exec.Command("ip", "link", "del", ifName)
379 func setDevUpDown(dev, ns string, isUp bool) error {
386 c := []string{"ip", "link", "set", "dev", dev, op}
387 cmd := appendNetns(c, ns)
390 s := fmt.Sprintf("error bringing %s device %s!", dev, op)
396 func AddVethPair(ifName, peerName string) error {
397 cmd := exec.Command("ip", "link", "add", ifName, "type", "veth", "peer", "name", peerName)
400 return fmt.Errorf("creating veth pair failed: %v", err)
402 err = SetDevUp(ifName, "")
404 return fmt.Errorf("set link up failed: %v", err)
409 func addDelNetns(name string, isAdd bool) error {
416 cmd := exec.Command("ip", "netns", op, name)
417 _, err := cmd.CombinedOutput()
419 return errors.New("add/del netns failed")
424 func AddNetns(nsName string) error {
425 return addDelNetns(nsName, true)
428 func DelNetns(nsName string) error {
429 return addDelNetns(nsName, false)
432 func LinkSetNetns(ifName, ns string) error {
433 cmd := exec.Command("ip", "link", "set", "dev", ifName, "up", "netns", ns)
436 return fmt.Errorf("error setting device '%s' to netns '%s: %v", ifName, ns, err)
441 func NewCommand(s []string, ns string) *exec.Cmd {
442 return appendNetns(s, ns)
445 func appendNetns(s []string, ns string) *exec.Cmd {
448 // use default namespace
449 cmd = exec.Command(s[0], s[1:]...)
451 var args = []string{"netns", "exec", ns}
452 args = append(args, s[:]...)
453 cmd = exec.Command("ip", args...)
458 func addDelBridge(brName, ns string, isAdd bool) error {
465 var c = []string{"brctl", op, brName}
466 cmd := appendNetns(c, ns)
469 s := fmt.Sprintf("%s %s failed!", op, brName)
475 func AddBridge(brName string, ifs []string, ns string) error {
476 err := addDelBridge(brName, ns, true)
481 for _, v := range ifs {
482 c := []string{"brctl", "addif", brName, v}
483 cmd := appendNetns(c, ns)
486 s := fmt.Sprintf("error adding %s to bridge %s: %v", v, brName, err)
490 err = SetDevUp(brName, ns)