gobgp
gobgp copied to clipboard
Route Reflected 'echo' routes still being installed locally
This is a continuation of https://github.com/osrg/gobgp/issues/1804
When a route is added and is being reflected by route reflectors after its deleted it doesn't always withdraw the route properly and becomes a wedged route. Accepting these echo routes violates https://tools.ietf.org/html/rfc4271#section-6.3 where the next-hop ip is the ip of the receiver.
quote:
The IP address in the NEXT_HOP MUST meet the following criteria to be
considered semantically correct:
a) It MUST NOT be the IP address of the receiving speaker.
b) In the case of an EBGP, where the sender and receiver are one
IP hop away from each other, either the IP address in the
NEXT_HOP MUST be the sender's IP address that is used to
establish the BGP connection, or the interface associated with
the NEXT_HOP IP address MUST share a common subnet with the
receiving BGP speaker.
If the NEXT_HOP attribute is semantically incorrect, the error SHOULD
be logged, and the route SHOULD be ignored. In this case, a
NOTIFICATION message SHOULD NOT be sent, and the connection SHOULD
NOT be closed.
The AS_PATH attribute is checked for syntactic correctness. If the
path is syntactically incorrect, then the Error Subcode MUST be set
to Malformed AS_PATH.
docker run --rm --name gorr2 -d --network gobgp --ip 192.168.64.101 -v `pwd`/gorr2:/etc/gobgp:rw pierky/gobgp
docker run --rm --name go2 -d --network gobgp --ip 192.168.65.2 -v `pwd`/go2:/etc/gobgp:rw pierky/gobgp
docker exec go2 gobgp global rib add -a ipv4 20.0.0.0/24 aspath 7,1,20,300 local-pref 86
docker exec go2 gobgp global rib 20.0.0.0/24
Network Next Hop AS_PATH Age Attrs
*> 20.0.0.0/24 0.0.0.0 7 1 20 300 00:00:04 [{Origin: ?} {LocalPref: 86}]
* 20.0.0.0/24 192.168.65.2 7 1 20 300 00:00:04 [{Origin: ?} {LocalPref: 86} {Originator: 192.168.64.101} {ClusterList: [192.168.64.100]}]
* 20.0.0.0/24 192.168.65.2 7 1 20 300 00:00:04 [{Origin: ?} {LocalPref: 86} {Originator: 192.168.64.100} {ClusterList: [192.168.64.100]}]
docker exec go2 gobgp global rib del -a ipv4 20.0.0.0/24 aspath 7,1,20,300 local-pref 86
docker exec go2 gobgp global rib 20.0.0.0/24
Network Next Hop AS_PATH Age Attrs
*> 20.0.0.0/24 192.168.65.2 7 1 20 300 00:00:26 [{Origin: ?} {LocalPref: 86} {Originator: 192.168.64.101} {ClusterList: [192.168.64.100]}]
* 20.0.0.0/24 192.168.65.2 7 1 20 300 00:00:26 [{Origin: ?} {LocalPref: 86} {Originator: 192.168.64.100} {ClusterList: [192.168.64.100]}]
cat gorr2/gobgp.conf
[global.config]
as = 65000
router-id = "192.168.64.101"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.64.2"
peer-as = 65000
auth-password = "$PASSWORD"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.64.100"
peer-as = 65000
auth-password = "$PASSWORD"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.65.1"
peer-as = 65000
auth-password = "$PASSWORD"
[neighbors.route-reflector.config]
route-reflector-client = true
route-reflector-cluster-id = "192.168.64.100"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.65.2"
peer-as = 65000
auth-password = "$PASSWORD"
[neighbors.route-reflector.config]
route-reflector-client = true
route-reflector-cluster-id = "192.168.64.100"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.65.3"
peer-as = 65000
auth-password = "$PASSWORD"
[neighbors.route-reflector.config]
route-reflector-client = true
route-reflector-cluster-id = "192.168.64.100"
cat go2/gobgp.conf
[global.config]
as = 65000
router-id = "192.168.65.2"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.64.2"
peer-as = 65000
auth-password = "$PASSWORD"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.64.100"
peer-as = 65000
auth-password = "$PASSWORD"
[[neighbors]]
[neighbors.config]
neighbor-address = "192.168.64.101"
peer-as = 65000
auth-password = "$PASSWORD"
I'm also noticing that Route Reflection in gobgp seems to set originator incorrectly. Please see https://tools.ietf.org/html/rfc4456#section-8
8. Avoiding Routing Information Loops
When a route is reflected, it is possible through misconfiguration to
form route re-distribution loops. The route reflection method
defines the following attributes to detect and avoid routing
information loops:
ORIGINATOR_ID
ORIGINATOR_ID is a new optional, non-transitive BGP attribute of Type
code 9. This attribute is 4 bytes long and it will be created by an
RR in reflecting a route. This attribute will carry the BGP
Identifier of the originator of the route in the local AS. A BGP
speaker SHOULD NOT create an ORIGINATOR_ID attribute if one already
exists. A router that recognizes the ORIGINATOR_ID attribute SHOULD
ignore a route received with its BGP Identifier as the ORIGINATOR_ID.
CLUSTER_LIST
CLUSTER_LIST is a new, optional, non-transitive BGP attribute of Type
code 10. It is a sequence of CLUSTER_ID values representing the
reflection path that the route has passed.
When an RR reflects a route, it MUST prepend the local CLUSTER_ID to
the CLUSTER_LIST. If the CLUSTER_LIST is empty, it MUST create a new
one. Using this attribute an RR can identify if the routing
information has looped back to the same cluster due to
misconfiguration. If the local CLUSTER_ID is found in the
CLUSTER_LIST, the advertisement received SHOULD be ignored.
When gobgp receives a route from a rrclient and reflects the route it sets its own ip to the originator vs that of the client.
docker exec go2 gobgp global rib 20.0.0.0/24
Network Next Hop AS_PATH Age Attrs
*> 20.0.0.0/24 0.0.0.0 7 1 20 300 00:00:04 [{Origin: ?} {LocalPref: 86}]
* 20.0.0.0/24 192.168.65.2 7 1 20 300 00:00:04 [{Origin: ?} {LocalPref: 86} {Originator: 192.168.64.101} {ClusterList: [192.168.64.100]}]
* 20.0.0.0/24 192.168.65.2 7 1 20 300 00:00:04 [{Origin: ?} {LocalPref: 86} {Originator: 192.168.64.100} {ClusterList: [192.168.64.100]}]