diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go index e74a660ab859e00b2d70f66175ddc6c750ffd495..3313923e6c7692aa8035d1ab697d3fa6e2e21c13 100644 --- a/protocols/bgp/server/fsm_established.go +++ b/protocols/bgp/server/fsm_established.go @@ -217,6 +217,7 @@ func (s *establishedState) updates(u *packet.BGPUpdate) { Type: route.BGPPathType, BGPPath: &route.BGPPath{ Source: bnet.IPv4ToUint32(s.fsm.peer.addr), + EBGP: s.fsm.peer.localASN != s.fsm.peer.peerASN, }, } diff --git a/route/bgp_path.go b/route/bgp_path.go index 0ab7dc4b2a3f6a23d77be1a0613b68515a5d1604..509d39844ac25236eef26071052ee5410ec3921f 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -40,6 +40,9 @@ func (b *BGPPath) Compare(c *BGPPath) int8 { return -1 } + // 9.1.2.2. Breaking Ties (Phase 2) + + // a) if c.ASPathLen > b.ASPathLen { return 1 } @@ -48,6 +51,7 @@ func (b *BGPPath) Compare(c *BGPPath) int8 { return -1 } + // b) if c.Origin > b.Origin { return 1 } @@ -56,6 +60,7 @@ func (b *BGPPath) Compare(c *BGPPath) int8 { return -1 } + // c) if c.MED > b.MED { return 1 } @@ -64,6 +69,18 @@ func (b *BGPPath) Compare(c *BGPPath) int8 { return -1 } + // d) + if c.EBGP && !b.EBGP { + return -1 + } + + if !c.EBGP && b.EBGP { + return 1 + } + + // e) TODO: interiour cost (hello IS-IS and OSPF) + + // f) if c.BGPIdentifier < b.BGPIdentifier { return 1 } @@ -72,6 +89,7 @@ func (b *BGPPath) Compare(c *BGPPath) int8 { return -1 } + // g) if c.Source < b.Source { return 1 } @@ -143,6 +161,7 @@ func (b *BGPPath) better(c *BGPPath) bool { return false } +// Print all known information about a route in human readable form func (b *BGPPath) Print() string { origin := "" switch b.Origin { @@ -153,20 +172,29 @@ func (b *BGPPath) Print() string { case 2: origin = "IGP" } + + bgpType := "internal" + if b.EBGP { + bgpType = "external" + } + ret := fmt.Sprintf("\t\tLocal Pref: %d\n", b.LocalPref) ret += fmt.Sprintf("\t\tOrigin: %s\n", origin) ret += fmt.Sprintf("\t\tAS Path: %v\n", b.ASPath) + ret += fmt.Sprintf("\t\tBGP type: %s\n", bgpType) nh := uint32To4Byte(b.NextHop) ret += fmt.Sprintf("\t\tNEXT HOP: %d.%d.%d.%d\n", nh[0], nh[1], nh[2], nh[3]) ret += fmt.Sprintf("\t\tMED: %d\n", b.MED) ret += fmt.Sprintf("\t\tPath ID: %d\n", b.PathIdentifier) - ret += fmt.Sprintf("\t\tSource: %d\n", b.Source) + src := uint32To4Byte(b.Source) + ret += fmt.Sprintf("\t\tSource: %d.%d.%d.%d\n", src[0], src[1], src[2], src[3]) ret += fmt.Sprintf("\t\tCommunities: %v\n", b.Communities) ret += fmt.Sprintf("\t\tLargeCommunities: %v\n", b.LargeCommunities) return ret } +// Prepend the given BGPPath with the given ASN given times func (b *BGPPath) Prepend(asn uint32, times uint16) { if times == 0 { return diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go index 180e2aeca7d94d92e078528279ca89ff5a572936..e211479b0480a338259a0dccce1a66b060ebcfe1 100644 --- a/routingtable/adjRIBOut/adj_rib_out.go +++ b/routingtable/adjRIBOut/adj_rib_out.go @@ -58,9 +58,6 @@ func (a *AdjRIBOut) AddPath(pfx bnet.Prefix, p *route.Path) error { p = p.Copy() if !a.neighbor.IBGP && !a.neighbor.RouteServerClient { p.BGPPath.Prepend(a.neighbor.LocalASN, 1) - } - - if !a.neighbor.IBGP && !a.neighbor.RouteServerClient { p.BGPPath.NextHop = a.neighbor.LocalAddress } @@ -114,14 +111,19 @@ func (a *AdjRIBOut) RemovePath(pfx bnet.Prefix, p *route.Path) bool { } a.rt.RemovePath(pfx, p) - pathID, err := a.pathIDManager.releasePath(p) - if err != nil { - log.Warningf("Unable to release path: %v", err) - return true + + // If the neighbar has AddPath capabilities, try to find the PathID + if a.neighbor.CapAddPathRX { + pathID, err := a.pathIDManager.releasePath(p) + if err != nil { + log.Warningf("Unable to release path for prefix %s: %v", pfx.String(), err) + return true + } + + p = p.Copy() + p.BGPPath.PathIdentifier = pathID } - p = p.Copy() - p.BGPPath.PathIdentifier = pathID a.removePathFromClients(pfx, p) return true }