diff --git a/routingtable/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/routingtable/adjRIBIn/adj_rib_in.go deleted file mode 100644 index 2657f22334fac285fcf952d2bc996ce0a69a1094..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/adjRIBIn/adj_rib_in.go +++ /dev/null @@ -1,28 +0,0 @@ -package adjRIBIn - -import ( - "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/routingtable" -) - -// AdjRIBIn implements an Adjacency RIB In (for use with BGP) -type AdjRIBIn struct { - rt *routingtable.RoutingTable -} - -// New creates a new Adjacency RIB In -func New() *AdjRIBIn { - return &AdjRIBIn{ - rt: routingtable.New(), - } -} - -// AddPath adds a route to the AdjRIBIn. If prefix exists already it is replaced. -func (a *AdjRIBIn) AddPath(pfx *net.Prefix, p *routingtable.Path) { - -} - -// RemovePath removes prefix pfx from the AdjRIBIn -func (a *AdjRIBIn) RemovePath(pfx *net.Prefix, p *routingtable.Path) { - -} diff --git a/routingtable/routingtable/client_interface.go b/routingtable/routingtable/client_interface.go deleted file mode 100644 index 648bf40ae29738a7c9f85bf068183d2317d66120..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/client_interface.go +++ /dev/null @@ -1,12 +0,0 @@ -package routingtable - -import ( - "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/route" -) - -// RouteTableClient is the interface that every type of RIB must implement -type RouteTableClient interface { - AddPath(*net.Prefix, *route.Path) error - RemovePath(*net.Prefix, *route.Path) error -} diff --git a/routingtable/routingtable/client_manager.go b/routingtable/routingtable/client_manager.go deleted file mode 100644 index 08e2587aa0d9f50bcf59054765754cfe84166af0..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/client_manager.go +++ /dev/null @@ -1,21 +0,0 @@ -package routingtable - -type ClientManager struct { - clients map[RouteTableClient]struct{} // Ensures a client registers at most once - routingTable *RoutingTable -} - -func (c *ClientManager) Register(client RouteTableClient) { - if c.clients == nil { - c.clients = make(map[RouteTableClient]struct{}, 0) - } - c.clients[client] = struct{}{} - //c.routingTable.updateNewClient(client) -} - -func (c *ClientManager) Unregister(client RouteTableClient) { - if _, ok := c.clients[client]; !ok { - return - } - delete(c.clients, client) -} diff --git a/routingtable/routingtable/rib_interface.go b/routingtable/routingtable/rib_interface.go deleted file mode 100644 index 45afeb2605a13a3ca65bfb885950d0a3b2fc8692..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/rib_interface.go +++ /dev/null @@ -1,11 +0,0 @@ -package routingtable - -import ( - "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/route" -) - -type RIB interface { - AddPath(*net.Prefix, *route.Path) - RemovePath(*net.Prefix, *route.Path) -} diff --git a/routingtable/routingtable/table.go b/routingtable/routingtable/table.go deleted file mode 100644 index 6b8bcb6b39200b0710aa3de0899ce12c248ed846..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/table.go +++ /dev/null @@ -1,92 +0,0 @@ -package routingtable - -import ( - "sync" - - "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/route" -) - -// RoutingTable is a binary trie that stores prefixes and their paths -type RoutingTable struct { - root *node - mu sync.RWMutex -} - -// NewRoutingTable creates a new routing table -func NewRoutingTable() *RoutingTable { - return &RoutingTable{} -} - -// AddPath adds a path to the routing table -func (rt *RoutingTable) AddPath(pfx net.Prefix, p *route.Path) error { - rt.mu.Lock() - defer rt.mu.Unlock() - - if rt.root == nil { - rt.root = newNode(pfx, p, pfx.Pfxlen(), false) - return nil - } - - rt.root = rt.root.addPath(pfx, p) - return nil -} - -// RemovePath removes a path from the trie -func (rt *RoutingTable) RemovePath(pfx net.Prefix, p *route.Path) error { - rt.mu.Lock() - defer rt.mu.Unlock() - - rt.root.removePath(pfx, p) - return nil -} - -// LPM performs a longest prefix match for pfx on lpm -func (rt *RoutingTable) LPM(pfx net.Prefix) (res []*route.Route) { - rt.mu.RLock() - defer rt.mu.RUnlock() - - if rt.root == nil { - return nil - } - - rt.root.lpm(pfx, &res) - return res -} - -// Get get's the route for pfx from the LPM -func (rt *RoutingTable) Get(pfx net.Prefix) *route.Route { - rt.mu.RLock() - defer rt.mu.RUnlock() - - if rt.root == nil { - return nil - } - - res := rt.root.get(pfx) - if res == nil { - return nil - } - return res.route -} - -// GetLonger get's prefix pfx and all it's more specifics from the LPM -func (rt *RoutingTable) GetLonger(pfx net.Prefix) (res []*route.Route) { - rt.mu.RLock() - defer rt.mu.RUnlock() - - if rt.root == nil { - return []*route.Route{} - } - - return rt.root.get(pfx).dumpPfxs(res) -} - -// Dump dumps all routes in table rt into a slice -func (rt *RoutingTable) Dump() []*route.Route { - rt.mu.RLock() - defer rt.mu.RUnlock() - - res := make([]*route.Route, 0) - return rt.root.dump(res) -} diff --git a/routingtable/routingtable/table_test.go b/routingtable/routingtable/table_test.go deleted file mode 100644 index a2eb10f76f93046fe71e98e59998ff52e15283b5..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/table_test.go +++ /dev/null @@ -1,451 +0,0 @@ -package routingtable - -import ( - "testing" - - "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/route" - "github.com/stretchr/testify/assert" -) - -func TestAddPath(t *testing.T) { - tests := []struct { - name string - routes []*route.Route - expected *node - }{ - { - name: "Insert first node", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - }, - expected: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - skip: 8, - }, - }, - { - name: "Insert duplicate node", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - }, - expected: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - skip: 8, - }, - }, - { - name: "Insert triangle", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 9), nil), - route.NewRoute(net.NewPfx(strAddr("10.128.0.0"), 9), nil), - }, - expected: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - skip: 8, - l: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 9), nil), - }, - h: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.128.0.0"), 9), nil), - }, - }, - }, - { - name: "Insert disjunct prefixes", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - }, - expected: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 7), nil), - skip: 7, - dummy: true, - l: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - }, - h: &node{ - route: route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - skip: 16, - }, - }, - }, - { - name: "Insert disjunct prefixes plus one child low", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - expected: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 7), nil), - skip: 7, - dummy: true, - l: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - l: &node{ - skip: 1, - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - l: &node{ - skip: 1, - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - }, - }, - }, - h: &node{ - route: route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - skip: 16, - }, - }, - }, - { - name: "Insert disjunct prefixes plus one child high", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.128"), 25), nil), - }, - expected: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 7), nil), - skip: 7, - dummy: true, - l: &node{ - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - l: &node{ - skip: 1, - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - l: &node{ - skip: 1, - route: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - }, - }, - }, - h: &node{ - route: route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - skip: 16, - h: &node{ - route: route.NewRoute(net.NewPfx(strAddr("11.100.123.128"), 25), nil), - }, - }, - }, - }, - } - - for _, test := range tests { - rt := NewRoutingTable() - for _, route := range test.routes { - rt.AddPath(route.Prefix(), nil) - } - - assert.Equal(t, test.expected, rt.root) - } -} - -func TestGet(t *testing.T) { - tests := []struct { - name string - routes []*route.Route - needle net.Prefix - expected *route.Route - }{ - { - name: "Test 1: Search pfx and dump route + more specifics", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 8), - expected: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - }, - { - name: "Test 2: Search pfx and don't dump more specifics", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 8), - expected: route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - }, - { - name: "Test 3: Empty table", - routes: []*route.Route{}, - needle: net.NewPfx(strAddr("10.0.0.0"), 32), - expected: nil, - }, - { - name: "Test 4: Get Dummy", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 7), - expected: nil, - }, - { - name: "Test 5", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - needle: net.NewPfx(strAddr("11.100.123.0"), 24), - expected: route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - }, - { - name: "Test 4: Get nonexistent #1", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 10), - expected: nil, - }, - { - name: "Test 4: Get nonexistent #2", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 10), - expected: nil, - }, - } - - for _, test := range tests { - rt := NewRoutingTable() - for _, route := range test.routes { - rt.AddPath(route.Prefix(), nil) - } - p := rt.Get(test.needle) - - if p == nil { - if test.expected != nil { - t.Errorf("Unexpected nil result for test %q", test.name) - } - continue - } - - assert.Equal(t, test.expected, p) - } -} -func TestGetLonger(t *testing.T) { - tests := []struct { - name string - routes []*route.Route - needle net.Prefix - expected []*route.Route - }{ - { - name: "Test 1: Search pfx and dump route + more specifics", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 8), - expected: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - }, - }, - } - - for _, test := range tests { - rt := NewRoutingTable() - for _, route := range test.routes { - rt.AddPath(route.Prefix(), nil) - } - p := rt.GetLonger(test.needle) - - if p == nil { - if test.expected != nil { - t.Errorf("Unexpected nil result for test %q", test.name) - } - continue - } - - assert.Equal(t, test.expected, p) - } -} -func TestLPM(t *testing.T) { - tests := []struct { - name string - routes []*route.Route - needle net.Prefix - expected []*route.Route - }{ - { - name: "LPM for non-existent route", - routes: []*route.Route{}, - needle: net.NewPfx(strAddr("10.0.0.0"), 32), - expected: nil, - }, - { - name: "Positive LPM test", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - needle: net.NewPfx(167772160, 32), // 10.0.0.0/32 - expected: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - }, - }, - { - name: "Exact match", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("11.100.123.0"), 24), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 12), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - needle: net.NewPfx(strAddr("10.0.0.0"), 10), - expected: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), nil), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 10), nil), - }, - }, - } - - for _, test := range tests { - rt := NewRoutingTable() - for _, route := range test.routes { - rt.AddPath(route.Prefix(), nil) - } - assert.Equal(t, test.expected, rt.LPM(test.needle)) - } -} - -func TestRemovePath(t *testing.T) { - tests := []struct { - name string - routes []*route.Route - removePfx net.Prefix - removePath *route.Path - expected []*route.Route - }{ - { - name: "Remove a path that is the only one for a prefix", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - route.NewRoute(net.NewPfx(strAddr("10.128.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - }, - removePfx: net.NewPfx(strAddr("10.0.0.0"), 8), - removePath: &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }, - expected: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - route.NewRoute(net.NewPfx(strAddr("10.128.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - }, - }, - { - name: "Remove a path that is one of two for a prefix", - routes: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{ - LocalPref: 1000, - }, - }), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{ - LocalPref: 2000, - }, - }), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - route.NewRoute(net.NewPfx(strAddr("10.128.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - }, - removePfx: net.NewPfx(strAddr("10.0.0.0"), 8), - removePath: &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{ - LocalPref: 1000, - }, - }, - expected: []*route.Route{ - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 8), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{ - LocalPref: 2000, - }, - }), - route.NewRoute(net.NewPfx(strAddr("10.0.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - route.NewRoute(net.NewPfx(strAddr("10.128.0.0"), 9), &route.Path{ - Type: route.BGPPathType, - BGPPath: &route.BGPPath{}, - }), - }, - }, - } - - for _, test := range tests { - rt := NewRoutingTable() - for _, route := range test.routes { - for _, p := range route.Paths() { - rt.AddPath(route.Prefix(), p) - } - } - - rt.RemovePath(test.removePfx, test.removePath) - - rtExpected := NewRoutingTable() - for _, route := range test.expected { - for _, p := range route.Paths() { - rtExpected.AddPath(route.Prefix(), p) - } - } - - assert.Equal(t, rtExpected.Dump(), rt.Dump()) - } -} - -func strAddr(s string) uint32 { - ret, _ := net.StrToAddr(s) - return ret -} diff --git a/routingtable/routingtable/trie.go b/routingtable/routingtable/trie.go deleted file mode 100644 index 21e840df990a2798a290e36e9ac5c26233a4a894..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/trie.go +++ /dev/null @@ -1,228 +0,0 @@ -package routingtable - -import ( - "github.com/bio-routing/bio-rd/net" - "github.com/bio-routing/bio-rd/route" -) - -// node is a node in the compressed trie that is used to implement a routing table -type node struct { - skip uint8 - dummy bool - route *route.Route - l *node - h *node -} - -func getBitUint32(x uint32, pos uint8) bool { - return ((x) & (1 << (32 - pos))) != 0 -} - -func newNode(pfx net.Prefix, path *route.Path, skip uint8, dummy bool) *node { - n := &node{ - route: route.NewRoute(pfx, path), - skip: skip, - dummy: dummy, - } - return n -} - -func (n *node) removePath(pfx net.Prefix, p *route.Path) { - if n == nil { - return - } - - if n.route.Prefix() == pfx { - if n.dummy { - return - } - - if n.route.RemovePath(p) { - // FIXME: Can this node actually be removed from the trie entirely? - n.dummy = true - } - - return - } - - b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1) - if !b { - n.l.removePath(pfx, p) - return - } - n.h.removePath(pfx, p) - return -} - -func (n *node) lpm(needle net.Prefix, res *[]*route.Route) { - if n == nil { - return - } - - currentPfx := n.route.Prefix() - if currentPfx == needle && !n.dummy { - *res = append(*res, n.route) - return - } - - if !currentPfx.Contains(needle) { - return - } - - if !n.dummy { - *res = append(*res, n.route) - } - n.l.lpm(needle, res) - n.h.lpm(needle, res) -} - -func (n *node) dumpPfxs(res []*route.Route) []*route.Route { - if n == nil { - return nil - } - - if !n.dummy { - res = append(res, n.route) - } - - if n.l != nil { - res = n.l.dumpPfxs(res) - } - - if n.h != nil { - res = n.h.dumpPfxs(res) - } - - return res -} - -func (n *node) get(pfx net.Prefix) *node { - if n == nil { - return nil - } - - if n.route.Prefix() == pfx { - if n.dummy { - return nil - } - return n - } - - if n.route.Pfxlen() > pfx.Pfxlen() { - return nil - } - - b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1) - if !b { - return n.l.get(pfx) - } - return n.h.get(pfx) -} - -func (n *node) addPath(pfx net.Prefix, p *route.Path) *node { - currentPfx := n.route.Prefix() - if currentPfx == pfx { - n.route.AddPath(p) - n.dummy = false - return n - } - - // is pfx NOT a subnet of this node? - if !currentPfx.Contains(pfx) { - if pfx.Contains(currentPfx) { - return n.insertBefore(pfx, p, n.route.Pfxlen()-n.skip-1) - } - - return n.newSuperNode(pfx, p) - } - - // pfx is a subnet of this node - b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1) - if !b { - return n.insertLow(pfx, p, currentPfx.Pfxlen()) - } - return n.insertHigh(pfx, p, n.route.Pfxlen()) -} - -func (n *node) insertLow(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *node { - if n.l == nil { - n.l = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false) - return n - } - n.l = n.l.addPath(pfx, p) - return n -} - -func (n *node) insertHigh(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *node { - if n.h == nil { - n.h = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false) - return n - } - n.h = n.h.addPath(pfx, p) - return n -} - -func (n *node) newSuperNode(pfx net.Prefix, p *route.Path) *node { - superNet := pfx.GetSupernet(n.route.Prefix()) - - pfxLenDiff := n.route.Pfxlen() - superNet.Pfxlen() - skip := n.skip - pfxLenDiff - - pseudoNode := newNode(superNet, nil, skip, true) - pseudoNode.insertChildren(n, pfx, p) - return pseudoNode -} - -func (n *node) insertChildren(old *node, newPfx net.Prefix, newPath *route.Path) { - // Place the old node - b := getBitUint32(old.route.Prefix().Addr(), n.route.Pfxlen()+1) - if !b { - n.l = old - n.l.skip = old.route.Pfxlen() - n.route.Pfxlen() - 1 - } else { - n.h = old - n.h.skip = old.route.Pfxlen() - n.route.Pfxlen() - 1 - } - - // Place the new Prefix - newNode := newNode(newPfx, newPath, newPfx.Pfxlen()-n.route.Pfxlen()-1, false) - b = getBitUint32(newPfx.Addr(), n.route.Pfxlen()+1) - if !b { - n.l = newNode - } else { - n.h = newNode - } -} - -func (n *node) insertBefore(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *node { - tmp := n - - pfxLenDiff := n.route.Pfxlen() - pfx.Pfxlen() - skip := n.skip - pfxLenDiff - new := newNode(pfx, p, skip, false) - - b := getBitUint32(pfx.Addr(), parentPfxLen) - if !b { - new.l = tmp - new.l.skip = tmp.route.Pfxlen() - pfx.Pfxlen() - 1 - } else { - new.h = tmp - new.h.skip = tmp.route.Pfxlen() - pfx.Pfxlen() - 1 - } - - return new -} - -func (n *node) dump(res []*route.Route) []*route.Route { - if n == nil { - return res - } - - if !n.dummy { - res = append(res, n.route) - } - - res = n.l.dump(res) - res = n.h.dump(res) - return res -} diff --git a/routingtable/routingtable/trie_test.go b/routingtable/routingtable/trie_test.go deleted file mode 100644 index 7bbf46e11dcc2a19e3af36a012e81b65be326cad..0000000000000000000000000000000000000000 --- a/routingtable/routingtable/trie_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package routingtable - -import ( - "testing" -) - -func TestGetBitUint32(t *testing.T) { - tests := []struct { - name string - input uint32 - offset uint8 - expected bool - }{ - { - name: "test 1", - input: 167772160, // 10.0.0.0 - offset: 8, - expected: false, - }, - { - name: "test 2", - input: 184549376, // 11.0.0.0 - offset: 8, - expected: true, - }, - } - - for _, test := range tests { - b := getBitUint32(test.input, test.offset) - if b != test.expected { - t.Errorf("%s: Unexpected failure: Bit %d of %d is %v. Expected %v", test.name, test.offset, test.input, b, test.expected) - } - } -} diff --git a/routingtable/table.go b/routingtable/table.go index a75ba5cc78d297280ac782524e15041e952c9e41..6b8bcb6b39200b0710aa3de0899ce12c248ed846 100644 --- a/routingtable/table.go +++ b/routingtable/table.go @@ -20,6 +20,9 @@ func NewRoutingTable() *RoutingTable { // AddPath adds a path to the routing table func (rt *RoutingTable) AddPath(pfx net.Prefix, p *route.Path) error { + rt.mu.Lock() + defer rt.mu.Unlock() + if rt.root == nil { rt.root = newNode(pfx, p, pfx.Pfxlen(), false) return nil @@ -31,12 +34,18 @@ func (rt *RoutingTable) AddPath(pfx net.Prefix, p *route.Path) error { // RemovePath removes a path from the trie func (rt *RoutingTable) RemovePath(pfx net.Prefix, p *route.Path) error { + rt.mu.Lock() + defer rt.mu.Unlock() + rt.root.removePath(pfx, p) return nil } // LPM performs a longest prefix match for pfx on lpm func (rt *RoutingTable) LPM(pfx net.Prefix) (res []*route.Route) { + rt.mu.RLock() + defer rt.mu.RUnlock() + if rt.root == nil { return nil } @@ -47,6 +56,9 @@ func (rt *RoutingTable) LPM(pfx net.Prefix) (res []*route.Route) { // Get get's the route for pfx from the LPM func (rt *RoutingTable) Get(pfx net.Prefix) *route.Route { + rt.mu.RLock() + defer rt.mu.RUnlock() + if rt.root == nil { return nil } @@ -60,6 +72,9 @@ func (rt *RoutingTable) Get(pfx net.Prefix) *route.Route { // GetLonger get's prefix pfx and all it's more specifics from the LPM func (rt *RoutingTable) GetLonger(pfx net.Prefix) (res []*route.Route) { + rt.mu.RLock() + defer rt.mu.RUnlock() + if rt.root == nil { return []*route.Route{} } @@ -69,6 +84,9 @@ func (rt *RoutingTable) GetLonger(pfx net.Prefix) (res []*route.Route) { // Dump dumps all routes in table rt into a slice func (rt *RoutingTable) Dump() []*route.Route { + rt.mu.RLock() + defer rt.mu.RUnlock() + res := make([]*route.Route, 0) return rt.root.dump(res) } diff --git a/routingtable/trie.go b/routingtable/trie.go index 73e208d339086cc2dcdf04b2cb9fef4f7a087935..21e840df990a2798a290e36e9ac5c26233a4a894 100644 --- a/routingtable/trie.go +++ b/routingtable/trie.go @@ -1,8 +1,6 @@ package routingtable import ( - "fmt" - "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/route" ) @@ -131,9 +129,7 @@ func (n *node) addPath(pfx net.Prefix, p *route.Path) *node { // is pfx NOT a subnet of this node? if !currentPfx.Contains(pfx) { - fmt.Printf("The new Prefix is not a sub pfx of this node!\n") if pfx.Contains(currentPfx) { - fmt.Printf("The current nodes pfx is a subnet of the new one!\n") return n.insertBefore(pfx, p, n.route.Pfxlen()-n.skip-1) } @@ -148,31 +144,6 @@ func (n *node) addPath(pfx net.Prefix, p *route.Path) *node { return n.insertHigh(pfx, p, n.route.Pfxlen()) } -/*func (n *node) insert(route *route.Route) *node { - if n.route.Prefix() == route.Prefix() { - n.route.AddPaths(route.paths) - n.dummy = false - return n - } - - // is pfx NOT a subnet of this node? - if !n.route.Prefix().Contains(route.Prefix()) { - route.bestPaths() - if route.Prefix().Contains(n.route.Prefix()) { - return n.insertBefore(route, n.route.Pfxlen()-n.skip-1) - } - - return n.newSuperNode(route) - } - - // pfx is a subnet of this node - b := getBitUint32(route.Prefix().Addr(), n.route.Pfxlen()+1) - if !b { - return n.insertLow(route, n.route.Prefix().Pfxlen()) - } - return n.insertHigh(route, n.route.Pfxlen()) -}*/ - func (n *node) insertLow(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *node { if n.l == nil { n.l = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false) @@ -193,7 +164,6 @@ func (n *node) insertHigh(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *no func (n *node) newSuperNode(pfx net.Prefix, p *route.Path) *node { superNet := pfx.GetSupernet(n.route.Prefix()) - fmt.Printf("New supernet: %s\n", superNet.String()) pfxLenDiff := n.route.Pfxlen() - superNet.Pfxlen() skip := n.skip - pfxLenDiff