// Set the IP addr of a netlink interface func (driver *driver) setInterfaceIP(name string, rawIP string) error { var netlinkRetryTimer time.Duration netlinkRetryTimer = 2 iface, err := netlink.LinkByName(name) if err != nil { log.Debugf("error retrieving new OVS bridge netlink link [ %s ] allowing another [ %d ] seconds for the host to finish creating it..", bridgeName, netlinkRetryTimer) time.Sleep(netlinkRetryTimer * time.Second) iface, err = netlink.LinkByName(name) if err != nil { log.Debugf("error retrieving new OVS bridge netlink link [ %s ] allowing another [ %d ] seconds for the host to finish creating it..", bridgeName, netlinkRetryTimer) time.Sleep(netlinkRetryTimer * time.Second) iface, err = netlink.LinkByName(name) if err != nil { log.Fatalf("Abandoning retrieving the new OVS bridge link from netlink, Run [ ip link ] to troubleshoot the error: %s", err) return err } } } ipNet, err := netlink.ParseIPNet(rawIP) if err != nil { return err } addr := &netlink.Addr{ipNet, ""} return netlink.AddrAdd(iface, addr) }
func New(version string) (server.Driver, error) { network, _ := netlink.ParseIPNet("10.46.0.0/16") gateway, _ := netlink.ParseIPNet("10.46.0.1/32") pool := &routedPool{ id: "myPool", subnet: network, allocatedIPs: make(map[string]bool), gateway: gateway, } rnet := &routedNetwork{ endpoints: make(map[string]*routedEndpoint), } pool.allocatedIPs[fmt.Sprintf("%s", gateway)] = true return &driver{ version: version, pool: pool, network: rnet, }, nil }
// Set the IP addr of a link func (driver *driver) setInterfaceIP(name string, rawIP string) error { iface, err := netlink.LinkByName(name) if err != nil { return err } ipNet, err := netlink.ParseIPNet(rawIP) if err != nil { return err } addr := &netlink.Addr{IPNet: ipNet, Label: ""} return netlink.AddrAdd(iface, addr) }
func (driver *driver) CreateEndpoint(create *netApi.CreateEndpointRequest) (*netApi.CreateEndpointResponse, error) { log.Debugf("Create endpoint request %+v", create) var aliases []*net.IPNet endID := create.EndpointID reqIface := create.Interface log.Debugf("Requested Interface %+v", reqIface) log.Debugf("IP Aliases: %+v", reqIface.IPAliases) for _, ipa := range reqIface.IPAliases { ip, _ := netlink.ParseIPNet(ipa) aliases = append(aliases, ip) } addr, _ := netlink.ParseIPNet(reqIface.Address) ep := &routedEndpoint{ ipv4Address: addr, ipAliases: aliases, } driver.network.endpoints[endID] = ep log.Infof("Creating endpoint %s %+v", endID, nil) return nil, nil }
// Set the IP addr of a netlink interface func (driver *driver) setInterfaceIP(name string, rawIP string) error { iface, err := netlink.LinkByName(name) if err != nil { log.Debugf("error retrieving new OVS bridge link [ %s ] likely a race issue between ovs and netlink, retrying in 1 second..", bridgeName) time.Sleep(2 * time.Second) iface, err = netlink.LinkByName(name) if err != nil { log.Errorf("Error retrieving the new OVS bridge from netlink: %s", err) return err } } ipNet, err := netlink.ParseIPNet(rawIP) if err != nil { return err } addr := &netlink.Addr{ipNet, ""} return netlink.AddrAdd(iface, addr) }
func NewNetlinkRoute(ifname, dst, src, gw string, scope netlink.Scope) (*netlink.Route, error) { link, err := netlink.LinkByName(ifname) if err != nil { return nil, err } dstNet, err := netlink.ParseIPNet(dst) if err != nil { return nil, err } r := netlink.Route{ LinkIndex: link.Attrs().Index, Dst: dstNet, Src: net.ParseIP(src), Gw: net.ParseIP(gw), Scope: scope, } return &r, nil }
// Set the IP addr of a netlink interface func setInterfaceIP(name string, rawIP string) error { retries := 2 var iface netlink.Link var err error for i := 0; i < retries; i++ { iface, err = netlink.LinkByName(name) if err == nil { break } log.Debugf("error retrieving new OVS bridge netlink link [ %s ]... retrying", name) time.Sleep(2 * time.Second) } if err != nil { log.Fatalf("Abandoning retrieving the new OVS bridge link from netlink, Run [ ip link ] to troubleshoot the error: %s", err) return err } ipNet, err := netlink.ParseIPNet(rawIP) if err != nil { return err } addr := &netlink.Addr{ipNet, ""} return netlink.AddrAdd(iface, addr) }
//modrib receives route updates from BGP server and adds the endpoint func (self *OfnetBgp) modRib(path *api.Path) error { var nlri bgp.AddrPrefixInterface var nextHop string var macAddrStr string var portNo uint32 if len(path.Nlri) > 0 { nlri = &bgp.IPAddrPrefix{} err := nlri.DecodeFromBytes(path.Nlri) if err != nil { return err } } for _, attr := range path.Pattrs { p, err := bgp.GetPathAttribute(attr) if err != nil { return err } err = p.DecodeFromBytes(attr) if err != nil { return err } if p.GetType() == bgp.BGP_ATTR_TYPE_NEXT_HOP { nextHop = p.(*bgp.PathAttributeNextHop).Value.String() break } } if nextHop == "0.0.0.0" { return nil } if nlri == nil { return fmt.Errorf("no nlri") } endpointIPNet, _ := netlink.ParseIPNet(nlri.String()) log.Infof("Bgp Rib Received endpoint update for %v , with nexthop %v", endpointIPNet, nextHop) //check if bgp published a route local to the host epid := endpointIPNet.IP.Mask(endpointIPNet.Mask).String() //Check if the route is local if nextHop == self.routerIP { log.Info("This is a local route skipping endpoint create! ") return nil } if self.agent.endpointDb[nextHop] == nil { //the nexthop is not the directly connected eBgp peer macAddrStr = "" portNo = 0 } else { macAddrStr = self.agent.endpointDb[nextHop].MacAddrStr portNo = self.agent.endpointDb[nextHop].PortNo } ipmask := net.ParseIP("255.255.255.255").Mask(endpointIPNet.Mask) if path.IsWithdraw != true { epreg := &OfnetEndpoint{ EndpointID: epid, EndpointType: "external", IpAddr: endpointIPNet.IP, IpMask: ipmask, VrfId: 0, // FIXME set VRF correctly MacAddrStr: macAddrStr, Vlan: 1, OriginatorIp: self.agent.localIp, PortNo: portNo, Timestamp: time.Now(), } // Install the endpoint in datapath // First, add the endpoint to local routing table self.agent.endpointDb[epreg.EndpointID] = epreg err := self.agent.datapath.AddEndpoint(epreg) if err != nil { log.Errorf("Error adding endpoint: {%+v}. Err: %v", epreg, err) return err } } else { log.Info("Received route withdraw from BGP for ", endpointIPNet) endpoint := self.agent.getEndpointByIp(endpointIPNet.IP) if endpoint != nil { self.agent.datapath.RemoveEndpoint(endpoint) delete(self.agent.endpointDb, endpoint.EndpointID) } } return nil }
//modrib receives route updates from BGP server and adds the endpoint func (self *OfnetBgp) modRib(path *table.Path) error { var nlri bgp.AddrPrefixInterface var nextHop string var macAddrStr string var portNo uint32 nlri = path.GetNlri() nextHop = path.GetNexthop().String() if nextHop == "0.0.0.0" { return nil } if nlri == nil { return fmt.Errorf("no nlri") } endpointIPNet, _ := netlink.ParseIPNet(nlri.String()) log.Infof("Bgp Rib Received endpoint update for path %s", path.String()) //check if bgp published a route local to the host epid := self.agent.getEndpointIdByIpVrf(endpointIPNet.IP.Mask(endpointIPNet.Mask), "default") //Check if the route is local if nextHop == self.routerIP { log.Debugf("This is a local route skipping endpoint create! ") return nil } else if ep := self.agent.getEndpointByID(epid); ep != nil { if ep.EndpointType != "external" { log.Debugf("Endpoint was learnt via internal protocol. skipping update! ") return nil } } nhEpid := self.agent.getEndpointIdByIpVrf(net.ParseIP(nextHop), "default") if ep := self.agent.getEndpointByID(nhEpid); ep == nil { //the nexthop is not the directly connected eBgp peer macAddrStr = "" portNo = 0 } else { macAddrStr = ep.MacAddrStr portNo = ep.PortNo } ipmask := net.ParseIP("255.255.255.255").Mask(endpointIPNet.Mask) if path.IsWithdraw != true { epreg := &OfnetEndpoint{ EndpointID: epid, EndpointType: "external", IpAddr: endpointIPNet.IP, IpMask: ipmask, Vrf: "default", // FIXME set VRF correctly MacAddrStr: macAddrStr, Vlan: 1, OriginatorIp: self.agent.localIp, PortNo: portNo, Timestamp: time.Now(), } // Install the endpoint in datapath // First, add the endpoint to local routing table self.agent.endpointDb.Set(epreg.EndpointID, epreg) err := self.agent.datapath.AddEndpoint(epreg) if err != nil { log.Errorf("Error adding endpoint: {%+v}. Err: %v", epreg, err) return err } } else { log.Info("Received route withdraw from BGP for ", endpointIPNet) endpoint := self.agent.getEndpointByIpVrf(endpointIPNet.IP, "default") if endpoint != nil { self.agent.datapath.RemoveEndpoint(endpoint) self.agent.endpointDb.Remove(endpoint.EndpointID) } } return nil }
func TestSetIpAddress(t *testing.T) { _, mocker := testSetup(t) defer testTeardown(t, mocker) hFile, err := ioutil.TempFile("", "vic_set_ip_test_hosts") if err != nil { t.Errorf("Failed to create tmp hosts file: %s", err) } rFile, err := ioutil.TempFile("", "vic_set_ip_test_resolv") if err != nil { t.Errorf("Failed to create tmp resolv file: %s", err) } // give us a hosts file we can modify defer func(hosts, resolv string) { hostsFile = hosts resolvFile = resolv }(hostsFile, resolvFile) hostsFile = hFile.Name() resolvFile = rFile.Name() bridge := AddInterface("eth1", mocker) external := AddInterface("eth2", mocker) secondIP, _ := netlink.ParseIPNet("172.16.0.10/24") gwIP, _ := netlink.ParseIPNet("172.16.0.1/24") cfg := executor.ExecutorConfig{ Common: executor.Common{ ID: "ipconfig", Name: "tether_test_executor", }, Networks: map[string]*executor.NetworkEndpoint{ "bridge": &executor.NetworkEndpoint{ Common: executor.Common{ ID: bridge, // interface rename Name: "bridge", }, Network: executor.ContainerNetwork{ Common: executor.Common{ Name: "bridge", }, Default: true, Gateway: *gwIP, }, Static: &net.IPNet{ IP: localhost, Mask: lmask.Mask, }, }, "cnet": &executor.NetworkEndpoint{ Common: executor.Common{ ID: bridge, // no interface rename }, Network: executor.ContainerNetwork{ Common: executor.Common{ Name: "cnet", }, }, Static: secondIP, }, "external": &executor.NetworkEndpoint{ Common: executor.Common{ ID: external, // interface rename Name: "external", }, Network: executor.ContainerNetwork{ Common: executor.Common{ Name: "external", }, }, Static: &net.IPNet{ IP: gateway, Mask: gmask.Mask, }, }, }, } tthr, _ := StartTether(t, &cfg, mocker) defer func() { // prevent indefinite wait in tether - normally session exit would trigger this tthr.Stop() // wait for tether to exit <-mocker.Cleaned }() <-mocker.Started assert.NotNil(t, mocker.Interfaces["bridge"], "Expected bridge network if endpoints applied correctly") // check addresses bIface, _ := mocker.Interfaces["bridge"].(*Interface) assert.NotNil(t, bIface) assert.Equal(t, 2, len(bIface.Addrs), "Expected two addresses on bridge interface") eIface, _ := mocker.Interfaces["external"].(*Interface) assert.NotNil(t, eIface) assert.Equal(t, 1, len(eIface.Addrs), "Expected one address on external interface") }
func TestSetIpAddress(t *testing.T) { testSetup(t) defer testTeardown(t) bridge := AddInterface("eno1") external := AddInterface("eno2") secondIP, _ := netlink.ParseIPNet("172.16.0.10/24") gwIP, _ := netlink.ParseIPNet("172.16.0.1/24") cfg := metadata.ExecutorConfig{ Common: metadata.Common{ ID: "ipconfig", Name: "tether_test_executor", }, Networks: map[string]*metadata.NetworkEndpoint{ "bridge": &metadata.NetworkEndpoint{ Common: metadata.Common{ ID: bridge, // interface rename Name: "bridge", }, Network: metadata.ContainerNetwork{ Common: metadata.Common{ Name: "bridge", }, Default: true, Gateway: gwIP, }, Static: &net.IPNet{ IP: localhost, Mask: lmask.Mask, }, }, "cnet": &metadata.NetworkEndpoint{ Common: metadata.Common{ ID: bridge, // no interface rename }, Network: metadata.ContainerNetwork{ Common: metadata.Common{ Name: "cnet", }, }, Static: secondIP, }, "external": &metadata.NetworkEndpoint{ Common: metadata.Common{ ID: external, // interface rename Name: "external", }, Network: metadata.ContainerNetwork{ Common: metadata.Common{ Name: "external", }, }, Static: &net.IPNet{ IP: gateway, Mask: gmask.Mask, }, }, }, } tthr, _ := StartTether(t, &cfg) <-Mocked.Started // check addresses bIface := Mocked.Interfaces["bridge"].(*Interface) assert.NotNil(t, bIface) assert.Equal(t, 2, len(bIface.Addrs), "Expected two addresses on bridge interface") eIface := Mocked.Interfaces["external"].(*Interface) assert.NotNil(t, eIface) assert.Equal(t, 1, len(eIface.Addrs), "Expected one address on external interface") // prevent indefinite wait in tether - normally session exit would trigger this tthr.Stop() // wait for tether to exit <-Mocked.Cleaned }
// NewVeth creates a veth pair with the given name, moves the peer into the // namespace n, then renames the peer to dstName and assigns the provided ip. // If insideFn is not nil, also executes that function in the context of the // given namespace. func NewVeth(n netns.NsHandle, name, dstName, ip string, insideFn func(netlink.Link) error) (link *netlink.Veth, err error) { l := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{ Name: name, }, PeerName: name + "_", } if err = netlink.LinkAdd(l); err != nil { return } defer func() { if err != nil { netlink.LinkDel(l) } }() otherL, err := netlink.LinkByName(l.PeerName) if err != nil { return } if err = netlink.LinkSetNsFd(otherL, int(n)); err != nil { return } err = RunInNs(n, func() error { lo, err := netlink.LinkByName("lo") if err != nil { return err } err = netlink.LinkSetUp(lo) if err != nil { return err } l, err := netlink.LinkByName(name + "_") if err != nil { return err } if err = netlink.LinkSetName(l, dstName); err != nil { return err } l.Attrs().Name = dstName a, err := netlink.ParseIPNet(ip) if err != nil { return err } if err := netlink.AddrAdd(l, &netlink.Addr{IPNet: a}); err != nil { return err } if insideFn != nil { if err := insideFn(l); err != nil { return err } } if err = netlink.LinkSetUp(l); err != nil { return err } return nil }) if err != nil { return } if err = netlink.LinkSetUp(l); err != nil { return } link = l return }