2019-01-10 11:37:17 +01:00
|
|
|
package gobgp;
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/alice-lg/alice-lg/backend/sources/gobgp/apiutil"
|
|
|
|
"github.com/osrg/gobgp/pkg/packet/bgp"
|
|
|
|
|
|
|
|
aliceapi "github.com/alice-lg/alice-lg/backend/api"
|
|
|
|
api "github.com/osrg/gobgp/api"
|
|
|
|
|
|
|
|
"log"
|
|
|
|
"fmt"
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2019-01-10 12:53:37 +01:00
|
|
|
var families []api.Family = []api.Family{api.Family{
|
|
|
|
Afi: api.Family_AFI_IP,
|
|
|
|
Safi: api.Family_SAFI_UNICAST,
|
|
|
|
},api.Family{
|
|
|
|
Afi: api.Family_AFI_IP6,
|
|
|
|
Safi: api.Family_SAFI_UNICAST,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-02-22 09:34:21 +01:00
|
|
|
func NewRoutesResponse() (aliceapi.RoutesResponse) {
|
|
|
|
routes := aliceapi.RoutesResponse{}
|
|
|
|
routes.Imported = make(aliceapi.Routes,0)
|
|
|
|
routes.Filtered = make(aliceapi.Routes,0)
|
|
|
|
routes.NotExported = make(aliceapi.Routes,0)
|
|
|
|
return routes
|
|
|
|
}
|
2019-01-10 11:37:17 +01:00
|
|
|
|
2019-02-22 09:34:21 +01:00
|
|
|
func generatePeerId(peer *api.Peer) string {
|
2019-02-26 16:59:40 +01:00
|
|
|
return PeerHash(peer)
|
2019-02-22 09:34:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (gobgp *GoBGP) lookupNeighbour(neighborId string) (*api.Peer,error) {
|
|
|
|
|
|
|
|
peers, err := gobgp.GetNeighbours()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, peer := range peers {
|
|
|
|
peerId := generatePeerId(peer)
|
|
|
|
if neighborId == "" || peerId == neighborId {
|
|
|
|
return peer,nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("Could not lookup neighbour")
|
|
|
|
}
|
2019-01-10 11:37:17 +01:00
|
|
|
|
|
|
|
|
2019-02-22 09:34:21 +01:00
|
|
|
func (gobgp *GoBGP) GetNeighbours() ([]*api.Peer, error) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
|
|
defer cancel()
|
2019-01-10 11:37:17 +01:00
|
|
|
|
|
|
|
peerStream, err := gobgp.client.ListPeer(ctx, &api.ListPeerRequest{EnableAdvertised: true})
|
|
|
|
if err != nil {
|
2019-02-22 09:34:21 +01:00
|
|
|
return nil,err
|
2019-01-10 11:37:17 +01:00
|
|
|
}
|
2019-02-22 09:34:21 +01:00
|
|
|
|
|
|
|
peers := make([]*api.Peer,0)
|
|
|
|
|
2019-01-10 11:37:17 +01:00
|
|
|
for {
|
|
|
|
peer, err := peerStream.Recv()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
2019-02-22 09:34:21 +01:00
|
|
|
peers = append(peers, peer.Peer)
|
|
|
|
}
|
|
|
|
return peers,nil
|
|
|
|
}
|
|
|
|
func (gobgp *GoBGP) GetRoutes(peer *api.Peer, tableType api.TableType, rr *aliceapi.RoutesResponse) error {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
|
|
defer cancel()
|
2019-01-10 11:37:17 +01:00
|
|
|
|
2019-02-22 09:34:21 +01:00
|
|
|
for _, family := range families {
|
|
|
|
|
|
|
|
pathStream, err := gobgp.client.ListPath(ctx, &api.ListPathRequest{
|
|
|
|
Name: peer.State.NeighborAddress,
|
|
|
|
TableType: tableType,
|
|
|
|
Family: &family,
|
2019-05-09 10:57:08 +02:00
|
|
|
EnableFiltered: true,
|
2019-02-22 09:34:21 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
2019-01-10 12:53:37 +01:00
|
|
|
|
2019-02-26 16:59:40 +01:00
|
|
|
rib := make([]*api.Destination,0)
|
2019-02-22 09:34:21 +01:00
|
|
|
for {
|
|
|
|
_path, err := pathStream.Recv()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
2019-02-26 16:59:40 +01:00
|
|
|
} else if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return err
|
2019-02-22 09:34:21 +01:00
|
|
|
}
|
2019-02-26 16:59:40 +01:00
|
|
|
rib = append(rib, _path.Destination)
|
|
|
|
}
|
2019-02-22 09:34:21 +01:00
|
|
|
|
2019-02-26 16:59:40 +01:00
|
|
|
for _, d := range rib {
|
|
|
|
for _, path := range d.Paths {
|
2019-02-22 09:34:21 +01:00
|
|
|
r := aliceapi.Route{}
|
2019-02-26 16:59:40 +01:00
|
|
|
r.Id = fmt.Sprintf("%d_%s", path.Identifier, d.Prefix)
|
2019-02-22 09:34:21 +01:00
|
|
|
r.NeighbourId = generatePeerId(peer)
|
2019-02-26 16:59:40 +01:00
|
|
|
r.Network = d.Prefix
|
2019-02-22 09:34:21 +01:00
|
|
|
r.Interface = "Unknown"
|
|
|
|
r.Age = time.Now().Sub(time.Unix(path.Age.GetSeconds(),int64(path.Age.GetNanos())))
|
|
|
|
r.Primary = path.Best
|
|
|
|
|
|
|
|
attrs, _ := apiutil.GetNativePathAttributes(path)
|
|
|
|
|
|
|
|
r.Bgp.Communities = make(aliceapi.Communities,0)
|
|
|
|
r.Bgp.LargeCommunities = make(aliceapi.Communities,0)
|
|
|
|
r.Bgp.ExtCommunities = make(aliceapi.ExtCommunities,0)
|
|
|
|
for _, attr := range attrs {
|
|
|
|
switch attr.(type) {
|
|
|
|
case *bgp.PathAttributeMultiExitDisc:
|
|
|
|
med := attr.(*bgp.PathAttributeMultiExitDisc)
|
|
|
|
r.Bgp.Med = int(med.Value)
|
|
|
|
case *bgp.PathAttributeNextHop:
|
|
|
|
nh := attr.(*bgp.PathAttributeNextHop)
|
|
|
|
r.Gateway = nh.Value.String()
|
|
|
|
r.Bgp.NextHop = nh.Value.String()
|
|
|
|
case *bgp.PathAttributeLocalPref:
|
|
|
|
lp := attr.(*bgp.PathAttributeLocalPref)
|
|
|
|
r.Bgp.LocalPref = int(lp.Value)
|
|
|
|
case *bgp.PathAttributeOrigin:
|
|
|
|
origin := attr.(*bgp.PathAttributeOrigin)
|
|
|
|
switch origin.Value {
|
|
|
|
case bgp.BGP_ORIGIN_ATTR_TYPE_IGP:
|
|
|
|
r.Bgp.Origin = "IGP"
|
|
|
|
case bgp.BGP_ORIGIN_ATTR_TYPE_EGP:
|
|
|
|
r.Bgp.Origin = "EGP"
|
|
|
|
case bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE:
|
|
|
|
r.Bgp.Origin = "Incomplete"
|
|
|
|
}
|
|
|
|
case *bgp.PathAttributeAsPath:
|
|
|
|
aspath := attr.(*bgp.PathAttributeAsPath)
|
|
|
|
for _, aspth := range aspath.Value {
|
|
|
|
for _, as := range aspth.GetAS() {
|
|
|
|
r.Bgp.AsPath = append(r.Bgp.AsPath, int(as))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case *bgp.PathAttributeCommunities:
|
|
|
|
communities := attr.(*bgp.PathAttributeCommunities)
|
|
|
|
for _, community := range communities.Value {
|
|
|
|
_community := aliceapi.Community{int((0xffff0000&community)>>16),int(0xffff&community)}
|
|
|
|
r.Bgp.Communities = append(r.Bgp.Communities, _community)
|
|
|
|
}
|
|
|
|
|
|
|
|
case *bgp.PathAttributeExtendedCommunities:
|
|
|
|
communities := attr.(*bgp.PathAttributeExtendedCommunities)
|
|
|
|
for _, community := range communities.Value {
|
2019-02-26 16:59:40 +01:00
|
|
|
if _community, ok := community.(*bgp.TwoOctetAsSpecificExtended); ok {
|
|
|
|
r.Bgp.ExtCommunities = append(r.Bgp.ExtCommunities, aliceapi.ExtCommunity{_community.AS, _community.LocalAdmin})
|
|
|
|
}
|
2019-02-22 09:34:21 +01:00
|
|
|
}
|
|
|
|
case *bgp.PathAttributeLargeCommunities:
|
|
|
|
communities := attr.(*bgp.PathAttributeLargeCommunities)
|
|
|
|
for _, community := range communities.Values {
|
2019-02-26 16:59:40 +01:00
|
|
|
r.Bgp.LargeCommunities = append(r.Bgp.LargeCommunities, aliceapi.Community{int(community.ASN), int(community.LocalData1), int(community.LocalData2)})
|
2019-02-22 09:34:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.Metric = (r.Bgp.LocalPref + r.Bgp.Med)
|
|
|
|
if path.Filtered {
|
|
|
|
rr.Filtered = append(rr.Filtered, &r)
|
|
|
|
} else {
|
|
|
|
rr.Imported = append(rr.Imported, &r)
|
|
|
|
}
|
|
|
|
}
|
2019-01-10 11:37:17 +01:00
|
|
|
}
|
|
|
|
}
|
2019-02-26 16:59:40 +01:00
|
|
|
|
2019-02-22 09:34:21 +01:00
|
|
|
return nil
|
2019-01-10 11:37:17 +01:00
|
|
|
}
|