diff --git a/net/helper.go b/net/helper.go new file mode 100644 index 0000000000000000000000000000000000000000..efb6759637fab4d13a08b43908057226e723d511 --- /dev/null +++ b/net/helper.go @@ -0,0 +1,8 @@ +package net + +import "net" + +// IPv4ToUint32 converts an `net.IP` to an uint32 interpretation +func IPv4ToUint32(ip net.IP) uint32 { + return uint32(ip[0]) + uint32(ip[1])<<8 + uint32(ip[2])<<16 + uint32(ip[3])<<24 +} diff --git a/net/helper_test.go b/net/helper_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7503a6854d951e6a97bb0674945416b5bc52bc94 --- /dev/null +++ b/net/helper_test.go @@ -0,0 +1,32 @@ +package net + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func IPv4ToUint32Test(t *testing.T) { + tests := []struct { + input []byte + expected uint32 + }{ + { + input: []byte{192, 168, 1, 5}, + expected: 3232235781, + }, + { + input: []byte{10, 0, 0, 0}, + expected: 167772160, + }, + { + input: []byte{172, 24, 5, 1}, + expected: 2887255297, + }, + } + + for _, test := range tests { + res := IPv4ToUint32(test.input) + assert.Equal(t, test.expected, res) + } +} diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go index 5a3cd8aad1b63d7bd019af3fd100f193c823fdf7..051eaf03cd24f5d6c176935c7c288a1fe1e7c0f0 100644 --- a/protocols/bgp/server/fsm.go +++ b/protocols/bgp/server/fsm.go @@ -660,7 +660,11 @@ func (fsm *FSM) established() int { fsm.adjRIBIn = adjRIBIn.New() fsm.adjRIBIn.Register(fsm.rib) - fsm.adjRIBOut = adjRIBOut.New() + n := &routingtable.Neighbor{ + Type: route.BGPPathType, + Address: tnet.IPv4ToUint32(fsm.remote), + } + fsm.adjRIBOut = adjRIBOut.New(n) fsm.adjRIBOut.Register(fsm.updateSender) fsm.rib.RegisterWithOptions(fsm.adjRIBOut, routingtable.ClientOptions{BestOnly: true}) diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go index 580b86b8aa522f00b24e9af27825e6e7514bc00f..8691c5ac87f473946225a35a5fce4823a482c6a0 100644 --- a/routingtable/adjRIBOut/adj_rib_out.go +++ b/routingtable/adjRIBOut/adj_rib_out.go @@ -11,15 +11,17 @@ import ( // AdjRIBOut represents an Adjacency RIB In as described in RFC4271 type AdjRIBOut struct { - rt *routingtable.RoutingTable routingtable.ClientManager - mu sync.RWMutex + rt *routingtable.RoutingTable + neighbor *routingtable.Neighbor + mu sync.RWMutex } // New creates a new Adjacency RIB In -func New() *AdjRIBOut { +func New(neighbor *routingtable.Neighbor) *AdjRIBOut { a := &AdjRIBOut{ - rt: routingtable.NewRoutingTable(), + rt: routingtable.NewRoutingTable(), + neighbor: neighbor, } a.ClientManager = routingtable.NewClientManager(a) return a @@ -32,6 +34,10 @@ func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error // AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added. func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error { + if a.isOwnPath(p) { + return nil + } + a.mu.Lock() defer a.mu.Unlock() @@ -46,6 +52,10 @@ func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error { // RemovePath removes the path for prefix `pfx` func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool { + if a.isOwnPath(p) { + return false + } + a.mu.Lock() defer a.mu.Unlock() @@ -63,6 +73,19 @@ func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool { return true } +func (a *AdjRIBOut) isOwnPath(p *route.Path) bool { + if p.Type != a.neighbor.Type { + return false + } + + switch p.Type { + case route.BGPPathType: + return p.BGPPath.Source == a.neighbor.Address + } + + return false +} + func (a *AdjRIBOut) removePathsFromClients(pfx net.Prefix, paths []*route.Path) { for _, path := range paths { for _, client := range a.ClientManager.Clients() { @@ -71,6 +94,7 @@ func (a *AdjRIBOut) removePathsFromClients(pfx net.Prefix, paths []*route.Path) } } +// Print dumps all prefixes in the Adj-RIB func (a *AdjRIBOut) Print() string { a.mu.RLock() defer a.mu.RUnlock() diff --git a/routingtable/neighbor.go b/routingtable/neighbor.go new file mode 100644 index 0000000000000000000000000000000000000000..c7702ea49cb8f52fd43fd61d3bbf9f50c05782d7 --- /dev/null +++ b/routingtable/neighbor.go @@ -0,0 +1,10 @@ +package routingtable + +// Neighbor represents the attributes identifying a neighbor relationsship +type Neighbor struct { + // Addres is the IPv4 address of the neighbor as integer representation + Address uint32 + + // Type is the type / protocol used for routing inforation communitation + Type uint8 +}