Skip to content

Commit

Permalink
Support dynamic route ops with muti -hops.
Browse files Browse the repository at this point in the history
  • Loading branch information
byteocean committed Jun 7, 2022
1 parent 6416bb3 commit 436ea7a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ bak
*~
.idea/
cover.out
/vendor
5 changes: 5 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package metalbond

type Client interface {
SetOwner(mb *MetalBond)

AddRoute(vni VNI, dest Destination, nexthop NextHop) error
RemoveRoute(vni VNI, dest Destination, nexthop NextHop) error
}
Expand All @@ -32,3 +34,6 @@ func (c DummyClient) AddRoute(vni VNI, dest Destination, nexthop NextHop) error
func (c DummyClient) RemoveRoute(vni VNI, dest Destination, nexthop NextHop) error {
return nil
}

func (c DummyClient) SetOwner(mb *MetalBond) {
}
2 changes: 2 additions & 0 deletions metalbond.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ func NewMetalBond(config Config, client Client) *MetalBond {
client: client,
}

m.client.SetOwner(&m)

return &m
}

Expand Down
84 changes: 57 additions & 27 deletions netlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type NetlinkClient struct {
config NetlinkClientConfig
tunDevice netlink.Link
mtx sync.Mutex
mbOwner *MetalBond
}

type NetlinkClientConfig struct {
Expand All @@ -52,6 +53,10 @@ func NewNetlinkClient(config NetlinkClientConfig) (*NetlinkClient, error) {
}, nil
}

func (c *NetlinkClient) SetOwner(mb *MetalBond) {
c.mbOwner = mb
}

func (c *NetlinkClient) AddRoute(vni VNI, dest Destination, hop NextHop) error {
c.mtx.Lock()
defer c.mtx.Unlock()
Expand All @@ -61,39 +66,54 @@ func (c *NetlinkClient) AddRoute(vni VNI, dest Destination, hop NextHop) error {
return nil
}

nxtHops := c.mbOwner.routeTable.GetNextHopsByDestination(vni, dest)

err := c.updateRoute(vni, dest, nxtHops)
if err != nil {
return fmt.Errorf("failed to update route")
}

return nil

}

func (c *NetlinkClient) RemoveRoute(vni VNI, dest Destination, hop NextHop) error {
c.mtx.Lock()
defer c.mtx.Unlock()

nxtHops := c.mbOwner.routeTable.GetNextHopsByDestination(vni, dest)

table, exists := c.config.VNITableMap[vni]
if !exists {
return fmt.Errorf("No route table ID known for given VNI")
return fmt.Errorf("no route table ID known for given VNI")
}

_, dst, err := net.ParseCIDR(dest.Prefix.String())
if err != nil {
return fmt.Errorf("cannot parse destination prefix: %v", err)
}

encap := netlink.IP6tnlEncap{
Dst: net.ParseIP(hop.TargetAddress.String()),
Src: net.ParseIP("::"), // what source ip to put here? Metalbond object, m, does not contain this info yet.
}

route := &netlink.Route{
LinkIndex: c.tunDevice.Attrs().Index,
Dst: dst,
Encap: &encap,
Table: table,
Protocol: METALBOND_RT_PROTO,
} // by default, the route is already installed into the kernel table without explicite specification

if err := netlink.RouteAdd(route); err != nil {
return fmt.Errorf("cannot add route to %s (table %d) to kernel: %v", dest, table, err)
if len(nxtHops) == 0 {

route := &netlink.Route{
Dst: dst,
Table: table,
} // by default, the route is already installed into the kernel table without explicite specification

if err := netlink.RouteDel(route); err != nil {
return fmt.Errorf("cannot remove route to %s (table %d) from kernel: %v", dest, table, err)
}
} else {
err := c.updateRoute(vni, dest, nxtHops)
if err != nil {
return fmt.Errorf("failed to update route")
}
}

return nil
}

func (c *NetlinkClient) RemoveRoute(vni VNI, dest Destination, hop NextHop) error {
c.mtx.Lock()
defer c.mtx.Unlock()
func (c *NetlinkClient) updateRoute(vni VNI, dest Destination, nexthops []NextHop) error {

if c.config.IPv4Only && dest.IPVersion != IPV4 {
return nil
Expand All @@ -109,21 +129,31 @@ func (c *NetlinkClient) RemoveRoute(vni VNI, dest Destination, hop NextHop) erro
return fmt.Errorf("cannot parse destination prefix: %v", err)
}

encap := netlink.IP6tnlEncap{
Dst: net.ParseIP(hop.TargetAddress.String()),
Src: net.ParseIP("::"), // what source ip to put here? Metalbond object, m, does not contain this info yet.
var nextHopInfos []*netlink.NexthopInfo

for _, hop := range nexthops {

encap := netlink.IP6tnlEncap{
Dst: net.ParseIP(hop.TargetAddress.String()),
Src: net.ParseIP("::"),
}

nextHopInfos = append(nextHopInfos, &netlink.NexthopInfo{
LinkIndex: c.tunDevice.Attrs().Index,
Encap: &encap,
// other fields value to be decided
})
}

route := &netlink.Route{
LinkIndex: c.tunDevice.Attrs().Index,
Dst: dst,
Encap: &encap,
MultiPath: nextHopInfos,
Table: table,
Protocol: METALBOND_RT_PROTO,
} // by default, the route is already installed into the kernel table without explicite specification
}

if err := netlink.RouteDel(route); err != nil {
return fmt.Errorf("cannot remove route to %s (table %d) from kernel: %v", dest, table, err)
if err := netlink.RouteReplace(route); err != nil {
return fmt.Errorf("cannot update route to %s (table %d) to kernel: %v", dest, table, err)
}

return nil
Expand Down

0 comments on commit 436ea7a

Please sign in to comment.