Quick next-hop self tip

Recently when I was just chilling and doing my labs for the JNCIE exam 😛 I faced an issue with the next-hop self policy. It may sound funny but such trivial aspect took me about 20 mins to figure it out.

For those of you who don’t know, such a policy is usually applied when an EBGP speaking router wants to advertise prefixes from its EBGP neighbor to its IBGP neighbors. Since by default, BGP does not change the next-hop of the prefix received from a EBGP neighbor, other IBGP routers will receive such prefix with the next-hop unchanged. It will result with the “unusable” state of this received prefix and in the end such prefix will not be installed in routing table. IBGP neighbor simply doesn’t know where the unchanged next-hop is. Applying the next-hop self policy forces to change this behaviour and changes the next-hop to “self” which is this particular advertising router address.

Another walkaround of this default behaviour is of course: 

  • advertising the p2p EBGP prefix into an IGP as passive
  • export direct routes into IGP
  • static routing, or
  • enable IGP with EBGP peer – not recommended and honestly probably not often used method

But enough for the theory, let’s get to practice.

I have a couple of routers interconnected with each other, but for the sake of this blog we will focus on three of them. 

R1 is an EBGP speaking router – AS65111

R2 is its EBGP neighbor – AS65000

R3 is IBGP router which has session to R2

Topology and addresses look like the below:

My initial state of the BGP and policy configuration looked like this:

On R1:

tomek@vMX_R1> show bgp summary
Threading mode: BGP I/O
Groups: 1 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet6.0
                       1          1          0          0          0          0
inet.0
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.168.1.1           65000        249        251       0       1     1:51:38 Establ
  inet.0: 0/0/0/0
2001:db8:8000:4200::4       65000        249        249       0       3     1:51:27 Establ
  inet6.0: 1/1/1/0

So far so good. BGP sessions are established.

Let’s check whether we’re advertising anything to our EBGP neighbor which is the R2

tomek@vMX_R1> show route advertising-protocol bgp 192.168.1.1
inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop MED     Lclpref AS path
* 1.1.1.1/32              Self               I
* 23.0.0.0/22             Self               I

tomek@vMX_R1> show route advertising-protocol bgp 2001:db8:8000:4200::4
inet6.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop MED     Lclpref AS path
* 2001:db1::1/128         Self               I

Great!!! We’re advertising prefixes that we want.

Quick jump to R2:

tomek@vMX_R2> show bgp summary
Threading mode: BGP I/O
Groups: 3 Peers: 4 Down peers: 0
Table          Tot Paths Act Paths Suppressed    History Damp State Pending
inet6.0
                       1          1 0          0 0 0
inet.0
                       2          2 0          0 0 0
Peer                     AS InPkt OutPkt   OutQ Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
3.3.3.3               65000 255   259 0 0 1:54:24 Establ
  inet.0: 0/0/0/0
192.168.1.0           65111 257   253 0 0 1:54:33 2/2/2/0              0/0/0/0
2001:db8::3           65000 254   256 0 0 1:54:18 Establ
  inet6.0: 0/0/0/0
2001:db8:8000:4200::8       65111 256 254       0 0 1:54:22 Establ
  inet6.0: 1/1/1/0

This also looks fine. We have two sessions (v4 and v6) to our EBGP neighbor (R1) and two sessions to IBGP router (3.3.3.3 and 2001:db8::3 which are R3 v4 and v6 loopback addresses respectively advertised via IGP)

Let’s check whether we’re receiving anything from the R1

tomek@vMX_R2> show route receive-protocol bgp 192.168.1.0
inet.0: 17 destinations, 17 routes (17 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop MED     Lclpref AS path
* 1.1.1.1/32              192.168.1.0               65111 I
* 23.0.0.0/22             192.168.1.0               65111 I
inet6.0: 18 destinations, 18 routes (18 active, 0 holddown, 0 hidden)

tomek@vMX_R2> show route receive-protocol bgp 2001:db8:8000:4200::8
inet.0: 17 destinations, 17 routes (17 active, 0 holddown, 0 hidden)
inet6.0: 18 destinations, 18 routes (18 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop MED     Lclpref AS path
* 2001:db1::1/128         2001:db8:8000:4200::8               65111 I

Ok. That looks good as well. So, we want to advertise those prefixes to the R3, but we also want to change the next-hop to self.

My initial policy and bgp configuration looked like this:

tomek@vMX_R2> show configuration protocols bgp
group EBGP {
    neighbor 2001:db8:8000:4200::8 {
        authentication-key "$9$v5cMNVDjHP5zFnyeWL-dqmP"; ## SECRET-DATA
        export to-as65111;
        peer-as 65111;
    }
    neighbor 192.168.1.0 {
        authentication-key "$9$v5cMNVDjHP5zFnyeWL-dqmP"; ## SECRET-DATA
        peer-as 65111;
    }
}
group IBGP {
    type internal;
    export nhs;
    neighbor 2001:db8::3 {
        local-address 2001:db8::2;
    }
    neighbor 3.3.3.3 {
        local-address 2.2.2.2;
    }
}
tomek@vMX_R2> show configuration policy-options policy-statement nhs
term 1 {
    from protocol bgp;
    then {
        next-hop self;
    }
}
term 2 {
    then reject;
}

Verification:

tomek@vMX_R2> show route advertising-protocol bgp 3.3.3.3

tomek@vMX_R2> show route advertising-protocol bgp 2001:db8::3

….and what the heck?!

Where are my prefixes? 🙂

This was my first bgp setup in a few months. I did not use it recently. But my policy seems to look fine. 

Next-hop self action – check, finishing term – check. And I usually add it since the BGP tends to advertise everything from bgp by default. 

But here is my MEMERROR() issue. It took me 20 mins to figure it out. I just forgot that the next-hop self will not do anything in my configuration.

The default policy for bgp is to export all prefixes received from bgp protocol. When my policy ends with reject statement, then there is no advertisement.

When I change my policy to:

tomek@vMX_R2> show configuration policy-options policy-statement nhs
term 1 {
    from protocol bgp;
    then {
        next-hop self;
        accept;
    }
}
term 2 {
    then reject;
}

Or remove the second term:

tomek@vMX_R2> show configuration policy-options policy-statement nhs
term 1 {
    from protocol bgp;
    then {
        next-hop self;
    }
}

All prefixes are properly advertised:

tomek@vMX_R2> show route advertising-protocol bgp 3.3.3.3
inet.0: 17 destinations, 17 routes (17 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop MED     Lclpref AS path
* 1.1.1.1/32              Self   100 65111 I
* 23.0.0.0/22             Self   100 65111 I

tomek@vMX_R2> show route advertising-protocol bgp 2001:db8::3
inet6.0: 18 destinations, 18 routes (18 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop MED     Lclpref AS path
* 2001:db1::1/128         Self   100 65111 I

When I only have one term with the next-hop self, then the finishing action is “accept”, which is a default policy in bgp. I’m writing this because you can often see an example of next-hop self policy as just: next-hop self. And if you won’t remember of a default bgp policy you can stuck debugging as I was. 

So, remember those wise words kids. Next-hop self is NOT a terminating (or rather flow control) action. It just changes the route characteristics.

And lastly a quick Route Reflector next-hop self consideration.

Applying next-hop self policy on a RR can be tricky, since you can end up with suboptimal routing in your network. But what to do when you RR is also injecting EBGP routes to your AS?

Just limit your NHS policy to the EBGP neighbor or interface for example:

[edit policy-options policy-statement restricted-nhs]
user@router# show
term only-from-EBGP {
    from {
        protocol bgp;
        neighbor <your EBGP neighbor address>;
    }
    then {
        next-hop self;
    }
}