BGP 101

Starting the Routing Process

Define the routing process

Only one BGP process can run on a router and it can be started using:

R(config)# router bgp AS-NUMBER

The AS Number used to be a 16 bits number ranging from 0 to 65535. According to RFC 4893, the AS number can have 32 bits starting from 0.0 to 65535.65535.

  • 0 – reserved

  • 1 – 64495 – assignable by IANA for public use

  • 64496 – 64511 – reserved for documentation

  • 64512 – 65534 – assigned for private use

  • 65535 - reserved

For details, see IANA.

Specify neighbors manually

BGP does not have a method to autodetect neighbors. Instead, each neighbor must be manually defined. See Neighbors.

Route advertising

By default, BGP will not advertise any route to its BGP peers. You will have to either redistribute a route from another protocol (redistribute command) or statically define a route that should be advertised (network command). BGP will only advertise routes that already exist in the routing table.


R(config-router)# redistribute ... 

Static network definition

R(config-router)# network NETWORK-ADDRESS [mask NETMASK]
! If NETMASK is missing, the default mask of the classful address is used

The exact NETWORK-ADDRESS/NETMASK must exist in the routing table, or the route will not be advertised!

Inject Maps

You can inject routes that do not exist in the routing table using an inject map. A less specific aggregate route must exist in the routing table.

R(config-router)# bgp inject-map INJECT-MAP exist-map EXIST-MAP [copy-attributes]
! copy-attributes will copy attributes from the aggregate route to the injected routes

The INJECT-MAP will set the prefixes that are to be inserted.

R(config)# route-map INJECT-MAP
R(config-route-map)# set ip address prefix-list INJECTED-ADDRESS

The EXIST-MAP will match the aggregate route and the neighbor that advertised it to us:

R(config)# route-map EXIST-MAP
R(config-route-map)# match ip address prefix-list AGGREGATE-ROUTE
R(config-route-map)#  match ip route-source prefix-list ROUTE-SOURCE
! Both match lines must be configured!


BGP does not have a method to autodetect neighbors. Instead, each neighbor must be manually defined:

R(config-router)# neighbor NEIGH-ADDR remote-as NEIGH-AS-NUMBER

Each router will attempt to create a TCP connection over port 179 with the neighbor. Depending on the NEIGH-AS-NUMBER, the peering will be considered internal or external and will act differently. BGP also offers the possibility to temporarily disable a neighbor by using the following command:

R(config-router)# neighbor NEIGH-ADDR shutdown

Peer Groups and Peer Templates

You can also create a group of neighbors and apply the same setting to all of them. First define the group and configure it with a remote AS:

R(config-router)# neighbor PEER-GROUP peer-group
R(config-router)# neighbor PEER-GROUP remote-as AS-NUMBER

Make other configurations to the PEER-GROUP and then define neighbors as members of the PEER-GROUP:

R(config-router)# neighbor NEIGH-ADDR peer-group PEER-GROUP

Another option is to use a Peer Template. There are 2 types of templates: session and policy templates. Session templates define parameters that make the 2 peers to become neighbors. First define the template:

R(config-router)# template peer-session PEER-TEMPLATE
R(config-router-stmp)# remote-as AS-NUMBER
! You can inherit another template and/or define other parameters
R(config-router-stmp)# inherit peer-session OTHER-TEMPLATE
R(config-router-stmp)# ...

In the same way, you can define and a policy template, only this template is used for policy definition for filtering, attribute modifications and so on:

R(config-router)# template peer-policy POLICY-TEMPLATE
R(config-router-ptmp)# ...

Then apply the template to the neighbor:

R(config-router)# neighbor NEIGH-ADDR inherit peer-session PEER-TEMPLATE
R(config-router)# neighbor NEIGH-ADDR inherit peer-policy POLICY-TEMPLATE

iBGP Peers

When the neighbors are in the same AS we have an internal BGP peering. BGP packets for iBGP peers will be sent with a TTL of 255 because BGP assumes the internal BGP peer is not directly connected, but a route to it exists in the routing table. It is important to remember the following rules regarding iBGP peers:

  • routes advertised to iBGP peers will not have the next hop modified. You can use next-hop-self to change this setting:

    R(config)# neighbor NEIGH-ADDR next-hop-self
  • routes advertised to iBGP peers will not have an AS_PATH prepended since we are advertising inside the same AS.

  • routes learned from iBGP peers will not be advertised to other iBGP peers to avoid loops. This is known as BGP Split Horizon rule. AS_PATH is used as a loop avoidance mechanism, and since all routers are in the same AS, we cannot use it inside the AS. BGP was designed considering that inside an AS, all BGP peers are fully meshed. In a fully meshed environment, all iBGP peers would exchange external BGP routes and they would have a similar view of the outside world. However, it is hard to satisfy this requirement in large networks, so there are workarounds: Route Reflectors and Confederations

Route Reflectors

By default, routes learned via iBGP peers are not advertised to other iBGP peers. By setting a neighbor as a route reflector client, this rule is changed like this:

  • If the iBGP route is received from a non route-reflector client peer, reflect the route only to route-reflector clients

  • If the iBGP route is received from a route-reflector client, reflect the route to all iBGP peers (router-reflector clients and non route-reflector clients)

It is as if a Route Reflector treats its clients as eBGP peers, but doesn’t do any AS_PATH prepending and doesn’t change the NEXT_HOP.

R(config-router)# neighbor NEIGH-ADDR route-reflector client


A confederation is a group of AS-es that appear to the exterior as a single AS. They will use the Confederation Identifier when peering with other routers that are not part of the same confederation and the locally defined AS number to peer with other members of the confederation. BGP updates learned from other sub-AS-es of a confederation are enclosed between () in the AS_PATH.

R(config)# router bgp SUB-AS-NUMBER
R(config-router)# bgp confederation identifier AS-NUMBER
R(config-router)# bgp confederation peers NEIGH-SUB-AS-NUMBER
! NEIGH-SUB-AS-NUMBER should list the other sub-AS-es of a confederation

Prefixes are passed between Sub-AS-es based on eBGP rules, but most attributes are left unchanged, like in iBGP, including the NEXT_HOP. Inside a Sub-AS, the peers should be fully meshed or use Route Reflectors.

Synchronization Rule

The synchronization rule applies only to iBGP updates and is used to prevent black holes – that is forwarding traffic to a BGP speaker via a non-BGP speaker that will drop all traffic for destinations known only via BGP. When synchronization is on, a router will not advertise routes, unless it has the same route in its IGP routing table. To overcome this rule, you can:

  1. Enable synchronization and Redistribute BGP in IGP

  2. Enable synchronization but run MPLS inside the AS – actually hiding the the packet destination and forwarding based on the MPLS label, thus preventing the blackhole

  3. Disable synchronization (default) if you know how to prevent the blackhole:

    R(config-router)# no synchronization

When using synchronization with redistribution, the BGP route will usually be marked with r – meaning RIB-failure. This happens because, by default, the IGP route has better AD than the BGP route. Still, the route will be considered valid and it will be advertised. To disable advertisement of RIB-failed routes, use:

R(config-router)# bgp suppress-inactive

The BGP Synchronization rule is independent from other BGP rules, like not advertising internal routes to other internal neighbors. When the IGP is OSPF, the route is considered synchronized only if it is received via BGP and OSPF from the same router. This means that the Router ID of OSPF and BGP must match on the advertising router.

eBGP peers

When the neighbors are in different AS-es we have an external BGP peering. BGP packets for eBGP peers are sent with a TTL of 1 by default, because BGP assumes eBGP peers are directly connected. Problems arise when the peers are not directly connected, and another router is between them. By default, the routers will not form a relationship because their packets don’t reach the other router. To solve this problem, you must change the TTL value of the BGP packets, using:

R(config-router)# neighbor NEIGH-ADDR ebgp-multihop [HOP-COUNT]
! Default HOP-COUNT: 255

The other option is to use the ttl-security feature:

R(config-router)# neighbor NEIGH-ADDR ttl-security hops MIN-HOPS

This time, the router will send eBGP packets with a TTL of 255, but will only accept packets from the neighbor if they have a TTL equal to or higher than the value defined in MIN-HOPS. This means that if the neighboring router is N hops away, you must set MIN-HOPS to a value equal to 255-N. You cannot configure both ebgp-multihop and ttl-security for the same neighbor.

The third option that can be used, is a special case where you use the Loopback addresses of each router as the source, but you still want to make them connect over a direct connection. Normally, a router will check if the eBGP peer is directly connected, and if not, it will give up on sending any packet, since it knows it’s TTL will expire. However, you can disable this check and send BGP packets with TTL=1 sourced and destined to the loopback interfaces, using the following steps:

! 1. set the loopback as the update source interface:
R(config-router)# neighbor NEIGH-ADDR update-source INTERFACE
! 2. disable connected check
R(config-router)# neighbor NEIGH-ADDR disable-connected-check

This configuration will allow peering between the loopbacks but will only use a directly connected network for sending the updates. A non-directly connected network will make the TTL expire in the BGP packets.

For eBGP advertisements we must remember the followings:

  • routes advertised to eBGP peers will have the next-hop set to the IP of the update’s source interface. The update’s source interface can be manually configured as below, or it is the interface used to send messages to the neighbor.

R(config)# neighbor NEIGH-ADDR update-source INTERFACE
  • routes advertised to eBGP peers will have the AS_PATH prepended with the AS of the sending router

  • routes learned from an eBGP are advertised to both iBGP and eBGP peers. Routes learned from iBGP peers are advertised only to eBGP peers

BGP Peering State Machine

  • IDLE – Waiting to start TCP connection

  • CONNECT – Waiting to complete TCP connection

  • ACTIVE -TCP Connection failed. Trying again

  • OPEN SENT – TCP Connection completed. OPEN message was sent

  • OPEN CONFIRM – OPEN message received, parameters agree upon, waiting for a keepalive

  • ESTABLISHED – Peering complete

2.5 Authentication

Authentication uses MD5 hashes and must be configured on each neighbor:

R(config-router)# neighbor NEIGH-ADDR password PASS


Keepalive and Holdtime

By default, the keepalive timer is 60 seconds, and the hold-time timer is 180 seconds.When a connection is started, BGP will negotiate the hold time with the neighbor. The smaller of the two hold times will be chosen. The keepalive timer is then set based on the negotiated hold time and the configured keepalive time.

R(config-router)# timers bgp KEEPALIVE HOLDTIME [MIN-HOLDTIME]
! MIN-HOLDTIME = MIN Holdtime from neighbor
! Default values: KEEPALIVE: 60 sec, HOLDTIME: 180 sec, MIN-HODLTIME: 0 sec

The timers can also be set for each neighbor:

R(config-router)# neighbor NEIGH-ADDR timers KEEPALIVE HOLDTIME [MIN-HOLDTIME]

Advertisement interval

BGP doesn’t send updates at regular intervals, instead it only sends triggered updates. But in order to prevent unnecessary propagation of link flaps, it will delay sending a new update until the Advertisement Timer expires. This timer starts as soon as the last update finished and it has a value of 5 seconds for iBGP peers and 30 seconds for eBGP peers. To modify it, use:

R(config-router)# neighbor NEIGH-ADDR advertisement-interval SEC
! Default SEC: 5 sec iBGP, 30 sec eBGP


  • OPEN – contains:

    • Local AS Number

    • Local Router ID

      1. Defined ID:

        R(config-router)# bgp router-id ROUTER-ID
      2. Highest IP of a loopback interface

      3. Highest IP of an up/up physical interface

    • Hold Time – negotiated to the lowest value

    • Other options

  • KEEPALIVE – By default sent every HoldTime/3 seconds

  • UPDATE– used to advertise or withdraw a prefix. Includes:

    • Withdrawn routes – routes that should be discared

    • NLRI (Network Layer Reachability Infromation) – routes being advertised

    • Path attributes

  • NOTIFICATION – sent when an error occurs that causes BGP connection to close


BGP uses router attributes to make routing decisions, unlike an IGP that uses link cost. However, when redistributing into BGP, the value of the IGP metric is copied into the MED attribute.

Administrative Distance

Default iBGP: 20 Default eBGP: 200

R(config-router)# distance AD SOURCE-IP WILDCARD ACL
R(config)# distance bgp EBGP-AD IBGP-AD LOCAL-AD



R(config-router)# neighbor NEIGH-ADDR distribute-list ACL

The ACL can be a standard ACL, in which case it will match on prefix bits but with any prefix length, or an extended ACL where it will match on both the prefix bits and the prefix length:

R(config)# access-list ACL {permit|deny} PREFIX PREFIX-WILDCARD MASK MASK-WILDCARD

Also, the distribute list can be applied to all the BGP process:

R(config-router)# distribute-list ACL {in|out} [INTERFACE]

Prefix List

R(config-router)# neighbor NEIGH-ADDR prefix-list PREFIX-LIST

A prefix list contains a list of permit or deny entires and ends with an impicit deny any. To define a prefix-list, use:

R(config)# ip prefix-list PREFIX-LIST NETWORK/LEN [ge MIN] [le MAX]
  1. If only the NETWORK/LEN appears in the prefix entry, it will only match this prefix.

  2. If the ge keyword is used, it will match all prefixes that have the first LEN bits the same as NETWORK and that have a subnet mask length between MIN and 32.

  3. If the le keyword is used, it will match all prefixes that have the first LEN bits the same as NETWORK and that have a subnet mask length between 0 and MAX.

  4. If both le and ge are used, it will match all prefixes that have the first LEN bits the same as NETWORK and that have a subnet mask length between MIN and MAX. Also, only entries where LEN<MIN<=MAX are valid.

Here are some examples:

R(config)# ip prefix-list EXAMPLE permit
! Matches only the default route
R(config)# ip prefix-list EXAMPLE le 32
! Matches any route
R(config)# ip prefix-list EXAMPLE {le MAX|ge MIN le MAX|ge MIN}
! Matches any routes with the subnet mask between 0-&gt;MAX, MIN-&gt;MAX or MIN-&gt;32 (le,le and ge,ge)
R(config)# ip prefix-list EXAMPLE {le MAX|ge MIN le MAX|ge MIN}
! Matches any route to a Class A destination with a mask between 0-&gt;MAX, MIN-&gt;MAX or MIN-&gt;32
R(config)# ip prefix-list EXAMPLE {le MAX|ge MIN le MAX|ge MIN}
! Matches any route to a Class B destination with a mask between 0-&gt;MAX, MIN-&gt;MAX or MIN-&gt;32
R(config)# ip prefix-list EXAMPLE {le MAX|ge MIN le MAX|ge MIN}
! Matches any route to a Class C destination with a mask between 0-&gt;MAX, MIN-&gt;MAX or MIN-&gt;32

Additionally, the distribute list can be applied to all the BGP process:

R(config-router)# distribute-list [gateway] PREFIX-LIST {in|out} [INTERFACE]
! Use gateway to filter based on route source


R(config-router)# neighbor NEIGH-ADDR filter-list AS-PATH-ACL {in|out}

To define an AS-PATH ACL, use:

R(config)# ip as-path access-list AS-PATH-ACL {permit|deny} REGEX
. = any character, including space
^ = beginning of string
$ = end of string
_ = ^$,() and space
\ = escape character
* = match zero or more occurances
+ = match one or more occurances
? = match zero or one occurances
! must be preceded by CTRL+V or ESC+Q to prevent ? character from being interpreted as HELP

A very useful command to test regular expressions is:

R# show ip bgp regexp REGEX

Some common REGEX values are:

.* - matches anything
^$ - matches empty string = Locally originated routes
^123_ - string that starts with 123 = Routes received from AS 123
_123$ - string that ends with 123 = Routes originated in AS 123
_123_ - string that contains 123 = Routes that passed through AS 123
^[0-9]+$ - string that only contains one number = Routes originated in a neighboring AS
\(([0-9]+)+\) - string that contains severa numbers between () = Routes that passed a confederation

Also check this section on regular expressions.


Read about COMMUNITY.

Advertise Maps

You can do conditional advertisement of routes using an advertise map:

R(config-router)# neighbor NEIGH-ADDR advertise-map ADVERTISE-MAP {exist-map EXIST-MAP|non-exist-map NON-EXIST-MAP}

The routes matched in the ADVERTISE-MAP are advertised if the routes matched in the EXIST-MAP exist in the BGP table, or if the routes matched in the NON-EXIST-MAP do not exist in the BGP table.


Auto Summary

Auto-summary only affects routes redistributed into BGP. By default, it is off. When on, it will summarize at the major network boundary

R(config-router)# auto-summary


An aggregate router can be sent instead of it’s longer prefix length children.

R(config-router)# aggregate-address SUMMARY-ADDR SUMMARY-MASK OPTIONS
! available OPTIONS:
! as-set
! summary-only
! attribute-map ATTRIBUTE-MAP
! advertise-map ADVERTISE-MAP
! suppress-map SUPPRESS-MAP
  • as-set = The default AS_PATH of an aggregate is empty: $^. When using this keyword the router will add the AS_SET to the AS_PATH. AS_SET is an unordered list of all ASes in the AS_PATH of all children routes. It appears between {} in the AS_PATH.

  • summary-only= by default, both the aggregate and its children are advertised. Using this keyword only the summary is advertised, all other are suppressed

  • attribute-map ATTRIBUTE-MAP = allows changing the attributes of the aggregate route

  • advertise-map ADVERTISE-MAP = allows you to select only a subset of the routes that will be used to generate the aggregate. The routes that are not matched will be advertised separately and the aggregate will not inherit their attributes.

  • suppress-map SUPPRESS-MAP = allows you to suppress a subset of the children routes. Routes that are matched by the route-map are suppressed

Routes that are suppressed can be unsuppressed per neighbor:

R(config-router)# neighbor NEIGH-ADDR unsuppress-map UNSUPPRESS-MAP

Routes that are matched in the UNSUPPRESS-MAP are advertised to the neighbor.

Use a static route to NULL0

Another option is to add a static route for the summary to NULL0 and then add that network to BGP:

R(config)# router bgp AS-NUMBER
R(config-router)# network SUMMARY-ADDR [mask SUMMARY-MASK]

This will add the summary to the BGP advertised routes but will also advertise all children prefixes. Additional filtering of those children may be required.

Default routes

Originate network

To add default routes to the BGP table you can use the network command if a default route already exists in the routing table:

R(config-router)# network

Redistribute routes to

Another option is to redistribute a route to into BGP. It won’t be enough to make it work. You also have to let BGP know you want it to advertise the default route. The route could be known via an IGP or via static routes. For example:

R(config)# ip route NULL0
! Have the default route in the routing table
R(config)# router bgp AS-NUMBER
R(config-router)# redistribute static [route-map ROUTE-MAP]
! Redistribute the default route into BGP
R(config-router)# default-information originate
! Let BGP knwo you want to advertise the default route

Advertise a default route to a neighbor

A simpler approach is to use the following command:

R(config-router)# neighbor NEIGH-ADDR default-originate

This configuration will always advertise a default route to a neighbor, but you can also define a condition for advertisement using a route map:

R(config-router)# neighbor NEIGH-ADDR default-originate route-map CONDITION-MAP


When redistributing from BGP to another protocol, only eBGP routes will be redistributed to prevent loops. Internal routes can be advertised using:

R(config-router)# bgp redistribute-internal

Take care when redistributing BGP in another protocol – the routes could be learned again from the IGP and usually this means that the IGP route will be preferred due to the lower AD. This may result in routing loops.

Last updated