Wednesday, January 11, 2017

Introduction to GoBGP Part 2

Published by Tim Epkes
 
This is part 2 of a multi-tutorial series on GoBGP.  Part 1 can be viewed at http://netreflection.blogspot.com/2017/01/introduction-to-gobgp.html and focused more on getting started.  In part 2 we will explore using multiple neighbors, with various policies per neighbor.  This tutorial assumes either Part 1 was reviewed or base familiarity with GoBGP.  Multiple AS's will be utilized as showing in figure 1.
Figure 1.

The configurations of each router are as follows:

R1 Base Configuration

[global.config]
  as = 65001
  router-id = "172.40.1.2"

[zebra]
  [zebra.config]
    enabled = true
    url = "unix:/var/run/quagga/zserv.api"
    redistribute-route-type-list = ["connect"]

[[neighbors]]
  [neighbors.config]
    neighbor-address = "172.40.1.3"
    peer-as = 65001
  [neighbors.route-reflector.config]
    route-reflector-client = true
    route-reflector-cluster-id = "172.40.1.2"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-labelled-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "l3vpn-ipv4-unicast"

[[neighbors]]
  [neighbors.config]
    neighbor-address = "172.40.2.3"
    peer-as = 65001
  [neighbors.route-reflector.config]
    route-reflector-client = true
    route-reflector-cluster-id = "172.40.1.2" 
 [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-labelled-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "l3vpn-ipv4-unicast"

[[neighbors]]
  [neighbors.config]
    neighbor-address = "192.65.1.3"
    peer-as = 65002
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
Figure 2.

One highlight to R1's configuration, as we have R2 and R3 in the same AS as R1, we have to make R1 a route-reflector to reflect routes from R2 to R3 and vice-versa.  Those configurations are highlighted in figure 2 with red letters.

R2 Base Configuration

[global.config]
  as = 65001
  router-id = "172.40.1.3"

[zebra]
  [zebra.config]
    enabled = true
    url = "unix:/var/run/quagga/zserv.api"
    redistribute-route-type-list = ["connect"]

[[neighbors]]
  [neighbors.config]
    neighbor-address = "172.40.1.2"
    peer-as = 65001
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-labelled-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "l3vpn-ipv4-unicast"

Figure 3.

R3 Base Configuration

[global.config]
  as = 65001
  router-id = "172.40.2.3"

[zebra]
  [zebra.config]
    enabled = true
    url = "unix:/var/run/quagga/zserv.api"
    redistribute-route-type-list = ["connect"]

[[neighbors]]
  [neighbors.config]
    neighbor-address = "172.40.2.2"
    peer-as = 65001
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-labelled-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "l3vpn-ipv4-unicast"
Figure 4.

R4 Base Configuration

[global.config]
  as = 65002
  router-id = "192.65.1.3"

[zebra]
  [zebra.config]
    enabled = true
    url = "unix:/var/run/quagga/zserv.api"
    redistribute-route-type-list = ["connect"]

[[neighbors]]
  [neighbors.config]
    neighbor-address = "192.65.1.2"
    peer-as = 65001
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
Figure 5.

To quickly show that all neighbors are established and exchanging routes, figure 6 is the output from R1's neighbors.

R1:~# gobgp neighbor
Peer          AS  Up/Down State       |#Advertised Received Accepted
172.40.1.3 65001 00:00:17 Establ      |          6        2        2
172.40.2.3 65001 00:00:15 Establ      |          6        2        2
192.65.1.3 65002 00:00:18 Establ      |          6        2        2
Figure 6.

Now R1 is going to generate routes, R4 will not get any routes with the community 100:50, R2 and R3 will not get any routes with the community 200:50.  But first we need to add those routes.  Figure 7 has the routes to be added.

Apply to R1
gobgp global rib add 10.50.1.0/24 origin igp nexthop 10.8.1.1 community 100:50 -a ipv4
gobgp global rib add 10.50.2.0/24 origin igp nexthop 10.8.1.1 community 100:50 -a ipv4
gobgp global rib add 10.50.3.0/24 origin igp nexthop 10.8.1.1 community 100:50 -a ipv4
gobgp global rib add 192.168.50.0/24 origin igp nexthop 10.8.1.1 community 200:50 -a ipv4
gobgp global rib add 192.201.0.0/16 origin igp nexthop 10.8.1.1 community 200:50 -a ipv4
Figure 7.

After applying the routes, each neighbor should be receiving 11 routes as shown in figure 8.

R1:~# gobgp neighbor    
Peer          AS  Up/Down State       |#Advertised Received Accepted
172.40.1.3 65001 00:17:59 Establ      |         11        2        2
172.40.2.3 65001 00:17:57 Establ      |         11        2        2
192.65.1.3 65002 00:18:00 Establ      |         11        2        2
Figure 8.

Now we need to create the following items:
  • Define neighbor sets
  • Define community sets
  • Define multiple policies
  • Attach the policy's globally.
First we start off creating our neighbor sets.  One will be for R4 in an external AS and the other will be for R2 and R3.

Add the configuration from figure 9 to R1
[[defined-sets.neighbor-sets]]
  neighbor-set-name = "ns1"
  neighbor-info-list = ["172.40.1.3","172.40.2.3"]

[[defined-sets.neighbor-sets]]
  neighbor-set-name = "extns1"
  neighbor-info-list = ["192.65.1.3"]
Figure 9.

Reload and verify the neighbor-sets are defined.
R1# gobgp policy neighbor
NAME    ADDRESS   
extns1  192.65.1.3
ns1     172.40.1.3
        172.40.2.3
Figure 10.

Now lets create the community-sets to be used in the policies.  Figure 11 has the community-sets to be added to R1.

[[defined-sets.bgp-defined-sets.community-sets]]
  community-set-name = "cs0"
  community-list = ["100:50"]

[[defined-sets.bgp-defined-sets.community-sets]]
  community-set-name = "cs1"
  community-list = ["200:50"]
Figure 11.

This time, we will hold off on applying until the remainder of the configuration is complete.  Now we need to create 2 policies, 1 which will restrict all internal routers from getting routes with community 200:50 and the other policy, which will prevent all routes with the community 100:50 from leaking outside AS 65001 (or to R4, the external site).  Figure 12 has he policies to be applied to R1.

[[policy-definitions]]
    name = "policy1"
    [[policy-definitions.statements]]
        name = "Drop community 200:50 to internal routers"
        [policy-definitions.statements.conditions.match-neighbor-set]
          neighbor-set = "ns1"
          match-set-options = "any"
        [policy-definitions.statements.conditions.bgp-conditions.match-community-set]
            community-set = "cs1"
            match-set-options = "any"
        [policy-definitions.statements.actions.route-disposition]
            accept-route = false

[[policy-definitions]]
    name = "policy2"
    [[policy-definitions.statements]]
        name = "Drop community 100:50 to external routers"
        [policy-definitions.statements.conditions.match-neighbor-set]
          neighbor-set = "extns1"
          match-set-options = "any"
        [policy-definitions.statements.conditions.bgp-conditions.match-community-set]
            community-set = "cs0"
            match-set-options = "any"
        [policy-definitions.statements.actions.route-disposition]
            accept-route = false
Figure 12.

After this we need to apply the policy globally.  We do this as depicted in figure 13.

[global.config]
  as = 65001
  router-id = "172.40.1.2"
[global.apply-policy.config]
  export-policy-list = ["policy1","policy2"]
Figure 13.

Next let's verify the policies are attached and properly defined.  Figure 14 has the output showing running policy.

R1:~# gobgp policy                                                                                              
Name policy1:
    StatementName Drop community 200:50 to internal routers:
      Conditions:
        NeighborSet: ANY ns1
        CommunitySet: ANY cs1
      Actions:
        REJECT
Name policy2:
    StatementName Drop community 100:50 to external routers:
      Conditions:
        NeighborSet: ANY extns1
        CommunitySet: ANY cs0
      Actions:
        REJECT
Figure 14.

Figure 15 shows a script to get what is being advertised out from R1 to each peer.  Notice the routes highlighted in red in accordance to the polices.

R1:~# for i in `gobgp neighbor |egrep -v "Peer" | awk '{print $1}'`
 do
   echo $i        
   gobgp neighbor $i adj-out
 done
 
OUTPUT: 
172.40.1.3
    Network             Next Hop             AS_PATH              Attrs
    10.8.1.0/24         172.40.1.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    10.8.3.0/24         172.40.2.3                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 172.40.2.3} {ClusterList: [172.40.1.2]}]
    10.20.0.0/24        192.65.1.3           65002                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 192.65.1.3} {ClusterList: [172.40.1.2]}]
    10.50.1.0/24        10.8.1.1                                  [{Origin: i} {LocalPref: 100} {Communities: 100:50} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    10.50.2.0/24        10.8.1.1                                  [{Origin: i} {LocalPref: 100} {Communities: 100:50} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    10.50.3.0/24        10.8.1.1                                  [{Origin: i} {LocalPref: 100} {Communities: 100:50} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    172.40.1.0/29       172.40.1.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    172.40.2.0/29       172.40.1.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    192.65.1.0/29       172.40.1.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
172.40.2.3
    Network             Next Hop             AS_PATH              Attrs
    10.8.1.0/24         172.40.2.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    10.8.2.0/24         172.40.1.3                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 172.40.1.3} {ClusterList: [172.40.1.2]}]
    10.20.0.0/24        192.65.1.3           65002                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 192.65.1.3} {ClusterList: [172.40.1.2]}]
    10.50.1.0/24        10.8.1.1                                  [{Origin: i} {LocalPref: 100} {Communities: 100:50} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    10.50.2.0/24        10.8.1.1                                  [{Origin: i} {LocalPref: 100} {Communities: 100:50} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    10.50.3.0/24        10.8.1.1                                  [{Origin: i} {LocalPref: 100} {Communities: 100:50} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    172.40.1.0/29       172.40.2.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    172.40.2.0/29       172.40.2.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
    192.65.1.0/29       172.40.2.2                                [{Origin: i} {Med: 0} {LocalPref: 100} {Originator: 0.0.0.0} {ClusterList: [172.40.1.2]}]
192.65.1.3
    Network             Next Hop             AS_PATH              Attrs
    10.8.1.0/24         192.65.1.2           65001                [{Origin: i} {Med: 0}]
    10.8.2.0/24         192.65.1.2           65001                [{Origin: i}]
    10.8.3.0/24         192.65.1.2           65001                [{Origin: i}]
    172.40.1.0/29       192.65.1.2           65001                [{Origin: i} {Med: 0}]
    172.40.2.0/29       192.65.1.2           65001                [{Origin: i} {Med: 0}]
    192.65.1.0/29       192.65.1.2           65001                [{Origin: i} {Med: 0}]
    192.168.50.0/24     10.8.1.1             65001                [{Origin: i} {Communities: 200:50}]
    192.201.0.0/16      10.8.1.1             65001                [{Origin: i} {Communities: 200:50}]

Figure 15.

Finally, as I always like to see the whole config after all the changes, here is the final configuration for R1:

[global.config]
  as = 65001
  router-id = "172.40.1.2"
[global.apply-policy.config]
  export-policy-list = ["policy1","policy2"]

[zebra]
  [zebra.config]
    enabled = true
    url = "unix:/var/run/quagga/zserv.api"
    redistribute-route-type-list = ["connect"]

[[neighbors]]
  [neighbors.config]
    neighbor-address = "172.40.1.3"
    peer-as = 65001
  [neighbors.route-reflector.config]
    route-reflector-client = true
    route-reflector-cluster-id = "172.40.1.2"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-labelled-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "l3vpn-ipv4-unicast"

[[neighbors]]
  [neighbors.config]
    neighbor-address = "172.40.2.3"
    peer-as = 65001
  [neighbors.route-reflector.config]
    route-reflector-client = true
    route-reflector-cluster-id = "172.40.1.2"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-labelled-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "l3vpn-ipv4-unicast"

[[neighbors]]
  [neighbors.config]
    neighbor-address = "192.65.1.3"
    peer-as = 65002
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv4-unicast"
  [[neighbors.afi-safis]]
    [neighbors.afi-safis.config]
      afi-safi-name = "ipv6-unicast"


[[defined-sets.neighbor-sets]]
  neighbor-set-name = "ns1"
  neighbor-info-list = ["172.40.1.3","172.40.2.3"]

[[defined-sets.neighbor-sets]]
  neighbor-set-name = "extns1"
  neighbor-info-list = ["192.65.1.3"]

[[defined-sets.bgp-defined-sets.community-sets]]
  community-set-name = "cs0"
  community-list = ["100:50"]

[[defined-sets.bgp-defined-sets.community-sets]]
  community-set-name = "cs1"
  community-list = ["200:50"]

[[policy-definitions]]
    name = "policy1"
    [[policy-definitions.statements]]
        name = "Drop community 200:50 to internal routers"
        [policy-definitions.statements.conditions.match-neighbor-set]
          neighbor-set = "ns1"
          match-set-options = "any"
        [policy-definitions.statements.conditions.bgp-conditions.match-community-set]
            community-set = "cs1"
            match-set-options = "any"
        [policy-definitions.statements.actions.route-disposition]
            accept-route = false

[[policy-definitions]]
    name = "policy2"
    [[policy-definitions.statements]]
        name = "Drop community 100:50 to external routers"
        [policy-definitions.statements.conditions.match-neighbor-set]
          neighbor-set = "extns1"
          match-set-options = "any"
        [policy-definitions.statements.conditions.bgp-conditions.match-community-set]
            community-set = "cs0"
            match-set-options = "any"
        [policy-definitions.statements.actions.route-disposition]
            accept-route = false

Hopefully you found this helpful.  In a part 3 that will come at a later time, we will explore a more complex setup and policy.

2 comments:

  1. Quick Note: Between the pull I used for this post and the current pull, there are changes in config syntax for policy. I'll get those posted up as soon as I can.

    ReplyDelete
  2. I finished testing the change in config. The change is just in the Policy actions definition. In the new git pull the change is active. The current config line is
    [policy-definitions.statements.actions.route-disposition]
    accept-route = false
    The new one is
    [policy-definitions.statements.actions]
    route-disposition] = "reject-route"

    ReplyDelete