Skip to content
Snippets Groups Projects
Commit aa5f6e2d authored by takt's avatar takt Committed by Daniel Czerwonk
Browse files

Basic Netlink protocol (#209)

parent 0b9c3830
Branches
Tags
No related merge requests found
File added
package main
import (
"os"
"time"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/kernel"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable/vrf"
log "github.com/sirupsen/logrus"
)
func main() {
vrf, err := vrf.New("inet.0")
if err != nil {
log.Errorf("Unable to create VRF: %v", err)
os.Exit(1)
}
rib4 := vrf.IPv4UnicastRIB()
rib4.AddPath(bnet.NewPfx(bnet.IPv4FromOctets(8, 8, 8, 0), 24), &route.Path{
Type: route.StaticPathType,
StaticPath: &route.StaticPath{
NextHop: bnet.IPv4FromOctets(127, 0, 0, 1),
},
})
k, err := kernel.New()
if err != nil {
log.Errorf("Unable to create protocol kernel: %v", err)
os.Exit(1)
}
defer k.Dispose()
rib4.Register(k)
time.Sleep(time.Second * 10)
}
package kernel
import (
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
)
type Kernel struct {
osKernel osKernel
}
type osKernel interface {
AddPath(pfx net.Prefix, path *route.Path) error
RemovePath(pfx net.Prefix, path *route.Path) bool
uninit() error
}
func New() (*Kernel, error) {
k := &Kernel{}
err := k.init()
if err != nil {
return nil, err
}
return k, nil
}
func (k *Kernel) AddPath(pfx net.Prefix, path *route.Path) error {
return k.osKernel.AddPath(pfx, path)
}
func (k *Kernel) RemovePath(pfx net.Prefix, path *route.Path) bool {
return k.osKernel.RemovePath(pfx, path)
}
func (k *Kernel) UpdateNewClient(routingtable.RouteTableClient) error {
return nil
}
func (k *Kernel) Register(routingtable.RouteTableClient) {
}
func (k *Kernel) RegisterWithOptions(routingtable.RouteTableClient, routingtable.ClientOptions) {
}
func (k *Kernel) Unregister(routingtable.RouteTableClient) {
}
func (k *Kernel) RouteCount() int64 {
return -1
}
func (k *Kernel) ClientCount() uint64 {
return 0
}
func (k *Kernel) Dump() []*route.Route {
return nil
}
func (k *Kernel) Dispose() {
k.osKernel.uninit()
}
package kernel
import (
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/pkg/errors"
"github.com/vishvananda/netlink"
bnet "github.com/bio-routing/bio-rd/net"
)
const (
protoBio = 45
)
func (k *Kernel) init() error {
lk, err := newLinuxKernel()
if err != nil {
return errors.Wrap(err, "Unable to initialize linux kernel")
}
err = lk.init()
if err != nil {
return errors.Wrap(err, "Init failed")
}
k.osKernel = lk
return nil
}
func (k *Kernel) uninit() error {
return k.osKernel.uninit()
}
type linuxKernel struct {
h *netlink.Handle
routes map[bnet.Prefix]struct{}
}
func newLinuxKernel() (*linuxKernel, error) {
h, err := netlink.NewHandle()
if err != nil {
return nil, errors.Wrap(err, "Unable to get Netlink handle")
}
return &linuxKernel{
h: h,
routes: make(map[bnet.Prefix]struct{}),
}, nil
}
func (lk *linuxKernel) init() error {
err := lk.cleanup()
if err != nil {
return errors.Wrap(err, "Cleanup failed")
}
return nil
}
func (lk *linuxKernel) uninit() error {
return lk.cleanup()
}
func (lk *linuxKernel) cleanup() error {
filter := &netlink.Route{
Protocol: protoBio,
}
routes, err := lk.h.RouteListFiltered(0, filter, netlink.RT_FILTER_PROTOCOL)
if err != nil {
return errors.Wrap(err, "Unable to get routes")
}
for i := range routes {
err = lk.h.RouteDel(&routes[i])
if err != nil {
return errors.Wrap(err, "Unable to remove route")
}
}
return nil
}
func (lk *linuxKernel) AddPath(pfx net.Prefix, path *route.Path) error {
r := &netlink.Route{
Protocol: protoBio,
Dst: pfx.GetIPNet(),
Gw: path.NextHop().ToNetIP(),
}
if _, found := lk.routes[pfx]; !found {
err := lk.h.RouteAdd(r)
if err != nil {
return errors.Wrap(err, "Unable to add route")
}
lk.routes[pfx] = struct{}{}
return nil
}
err := lk.h.RouteReplace(r)
if err != nil {
return errors.Wrap(err, "Unable to replace route")
}
return nil
}
func (lk *linuxKernel) RemovePath(pfx net.Prefix, path *route.Path) bool {
if _, found := lk.routes[pfx]; !found {
return false
}
r := &netlink.Route{
Protocol: protoBio,
Dst: pfx.GetIPNet(),
Gw: path.NextHop().ToNetIP(),
}
err := lk.h.RouteDel(r)
if err != nil {
return false
}
delete(lk.routes, pfx)
return true
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment