iBGP and AS_PATH prepend in IOS and Junos

Posted on Oct 7, 2026

This one was written and published almost ten years ago on Wordpress. I don’t remember why I was so bored to put the effort and collect this useless piece of information. It was the second and last post on that blog. I had completely forgotten about it until I received a notification about a comment in the blog.

“You know what . This post solved my issue today… Thumbs Up !!!!!!!”

I wasn’t expecting that a post about something nobody would ever do on their network would be helpful to someone. Life is full of surprises, and I probably underestimated my effort.

Since it helpded one, it could probably help more, right? That’s why I am bringing it back here, as the Wordpress blog is gone.

Enjoy!

Intro

AS_PATH prepend is commonly used to make specific links less desirable for traffic ingress to the AS. Typically, the local ASN is added (prepended) several times in the AS_PATH attribute of the BGP updates sent to eBGP peers. The longer AS_PATH is likely to make the receiving AS select a different path that is advertised with a shorter AS_PATH. BGP updates for routes originating within the AS sent to iBGP peers have an empty AS_PATH attribute. But what happens if you try to do AS_PATH prepend on updates sent to iBGP peers?

The BGP decision process clearly states that when a BGP update message is received the AS_PATH attribute is examined. If the local AS is listed in the AS_PATH the update is rejected. Configuring AS_PATH prepend for iBGP updates should then cause the sending router to include the local AS in the AS_PATH forcing the receiving router to reject the update because of the loop detected.

Let’s see how IOS and Junos behave in such a situation.

Topology

A description

Routers J1 and J2 run Junos. Router C1 runs Cisco IOS. J1 has iBGP peering with J2 and C1 and it is configured to prepend the local AS in the updates sent to J2 and to C1. J2 is not configured for AS_PATH prepending while C1 is.

Configurations

J1

interfaces {
    em0 {
        unit 0 {
            family inet {
                address 10.0.0.1/24;
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 192.168.1.1/32;
            }
        }
    }
}
policy-options {
    policy-statement TO_C1 {
        term INTERNAL {
            from {
                route-filter 192.168.1.1/32 exact;
            }
            then {
                as-path-prepend 65441;
                accept;
            }
        }
        term DEFAULT {
            then reject;
        }
    }
    policy-statement TO_J2 {
        term INTERNAL {
            from {
                route-filter 192.168.1.1/32 exact;
            }
            then {
                as-path-prepend 65441;
                accept;
            }
        }
        term DEFAULT {
            then reject;
        }
    }
}
routing-instances {
    TEST {
        instance-type virtual-router;
        interface em0.0;
        interface lo0.0;
        routing-options {
            router-id 192.168.1.1;
            autonomous-system 65441;
        }
        protocols {
            bgp {
                traceoptions {
                    file bgp_monitor size 50000 files 5 world-readable;
                    flag all;
                }
                group IBGP {
                    type internal;
                    neighbor 10.0.0.2 {
                        description J2;
                        export TO_J2;
                    }
                    neighbor 10.0.0.3 {
                        description C1;
                        export TO_C1;
                    }
                }
            }
        }
    }
}

J2

interfaces {
    em0 {
        unit 0 {
            family inet {
                address 10.0.0.2/24;
            }
        }
    }
    lo0 {
        unit 0 {
            family inet {
                address 192.168.1.2/32;
            }
        }
    }
}
policy-options {
    policy-statement TO_J1 {
        term INTERNAL {
            from {
                route-filter 192.168.1.2/32 exact;
            }
            then accept;
        }
        term DEFAULT {
            then reject;
        }
    }
}
routing-instances {
    TEST {
        instance-type virtual-router;
        interface em0.0;
        interface lo0.0;
        routing-options {
            router-id 192.168.1.2;
            autonomous-system 65441;
        }
        protocols {
            bgp {
                traceoptions {
                    file bgp_monitor size 50000 files 5 world-readable;
                    flag all;
                }
                group IBGP {
                    type internal;
                    neighbor 10.0.0.1 {
                        description J1;
                        export TO_J1;
                    }
                }
            }
        }
    }
}

C1

interface Loopback0
 ip address 192.168.1.3 255.255.255.255
!
interface Ethernet0/0
 ip address 10.0.0.3 255.255.255.0
!
router bgp 65441
 bgp log-neighbor-changes
 network 192.168.1.3 mask 255.255.255.255
 neighbor 10.0.0.1 remote-as 65441
 neighbor 10.0.0.1 soft-reconfiguration inbound
 neighbor 10.0.0.1 route-map TO_J1 out
 neighbor 10.0.0.2 remote-as 65441
 neighbor 10.0.0.2 shutdown
 neighbor 10.0.0.2 soft-reconfiguration inbound
!
ip prefix-list IBGP seq 5 permit 192.168.1.3/32
!
route-map TO_J1 permit 10
 match ip address prefix-list IBGP
 set as-path prepend 65441

Details

J1 sends the update to J2 with the local AS 65441 prepended in the AS_PATH.

jhn@J1> show route advertising-protocol bgp 10.0.0.2 detail

TEST.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
* 192.168.1.1/32 (1 entry, 1 announced)
 BGP group IBGP type Internal
     Nexthop: Self
     Localpref: 100
     AS path: 65441 [65441] I

Packet Capture

Frame 60: 144 bytes on wire (1152 bits), 144 bytes captured (1152 bits) on interface 0
Ethernet II, Src: CadmusCo_75:c8:a3 (08:00:27:75:c8:a3), Dst: CadmusCo_0d:c0:c7 (08:00:27:0d:c0:c7)
Internet Protocol Version 4, Src: 10.0.0.1, Dst: 10.0.0.2
Transmission Control Protocol, Src Port: 56071, Dst Port: 179, Seq: 98, Ack: 170, Len: 78
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 55
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 27
    Path attributes
        Path Attribute - ORIGIN: IGP
        Path Attribute - AS_PATH: 65441 
        Path Attribute - NEXT_HOP: 10.0.0.1 
        Path Attribute - LOCAL_PREF: 100
    Network Layer Reachability Information (NLRI)
        192.168.1.1/32
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 23
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 0

J2 does not install the route sent by J1…

jhn@J2> show route receive-protocol bgp 10.0.0.1 detail all

__juniper_private1__.inet.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)

__juniper_private2__.inet.0: 1 destinations, 1 routes (0 active, 0 holddown, 1 hidden)

TEST.inet.0: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)

__juniper_private1__.inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)

… because it detects the loop.

Log

Jan 25 11:19:47.612738 bgp_read_v4_message: receiving packet(s) from 10.0.0.1 (Internal AS 65441)
Jan 25 11:19:47.612746
Jan 25 11:19:47.612746 BGP RECV 10.0.0.1+179 -> 10.0.0.2+57558
Jan 25 11:19:47.612750 BGP RECV message type 4 (KeepAlive) length 19
Jan 25 11:19:47.612753
Jan 25 11:19:47.612753 BGP RECV 10.0.0.1+179 -> 10.0.0.2+57558
Jan 25 11:19:47.612756 BGP RECV message type 2 (Update) length 55
Jan 25 11:19:47.612758 BGP RECV Update PDU length 55
Jan 25 11:19:47.612761 BGP RECV flags 0x40 code Origin(1): IGP
Jan 25 11:19:47.612765 BGP RECV flags 0x40 code ASPath(2) length 6: 65441
Jan 25 11:19:47.612768 BGP RECV flags 0x40 code NextHop(3): 10.0.0.1
Jan 25 11:19:47.612770 BGP RECV flags 0x40 code LocalPref(5): 100
Jan 25 11:19:47.612776 BGP RECV         192.168.1.1/32
Jan 25 11:19:47.612802 bgp_should_merge_as2_and_as4_path():2051 AS4-Peer 10.0.0.1 (Internal AS 65441)(RECV): No merge of as-paths required as the peer is 4 byte as capable
Jan 25 11:19:47.612806 bgp_process_aspath_and_aggr_attr():2480 AS4-Peer 10.0.0.1 (Internal AS 65441)(RECV): bgp_should_merge_as2_and_as4_path() says NO
Jan 25 11:19:47.612810 bgp_process_aspath_and_aggr_attr():2517 AS4-Peer 10.0.0.1 (Internal AS 65441)(RECV): Merged asp: path_len 4, path_seg_len 2, path2_len 0, path2_seg_len 0, path4_len 0, path4_seg_len 0, path_attr_len 0, path_aggr_len 0, path4_aggr_len 0, path4_flags 0x0, path_flags 0x0
Jan 25 11:19:47.612825 As loop detected. Rejecting update
Jan 25 11:19:47.612839 bgp_rcv_nlri: Peer 10.0.0.1 (Internal AS 65441)
Jan 25 11:19:47.612845 bgp_rcv_nlri: 192.168.1.1/32
Jan 25 11:19:47.612850 bgp_rcv_nlri: Uninstall no route  192.168.1.1/32

J1 sends the update to C1 with AS_PATH prepended.

jhn@J1> show route advertising-protocol bgp 10.0.0.3 detail

TEST.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
* 192.168.1.1/32 (1 entry, 1 announced)
 BGP group IBGP type Internal
     Nexthop: Self
     Localpref: 100
     AS path: 65441 [65441] I

Packet Capture

Frame 48: 128 bytes on wire (1024 bits), 128 bytes captured (1024 bits) on interface 0
Ethernet II, Src: CadmusCo_75:c8:a3 (08:00:27:75:c8:a3), Dst: aa:bb:cc:00:01:00 (aa:bb:cc:00:01:00)
Internet Protocol Version 4, Src: 10.0.0.1, Dst: 10.0.0.3
Transmission Control Protocol, Src Port: 179, Dst Port: 15603, Seq: 79, Ack: 96, Len: 74
Border Gateway Protocol - KEEPALIVE Message
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 55
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 27
    Path attributes
        Path Attribute - ORIGIN: IGP
        Path Attribute - AS_PATH: 65441 
        Path Attribute - NEXT_HOP: 10.0.0.1 
        Path Attribute - LOCAL_PREF: 100
    Network Layer Reachability Information (NLRI)
        192.168.1.1/32

C1 accepts the route from J1 with AS_PATH prepended.

C1#sh ip bgp neighbors 10.0.0.1 received-routes
BGP table version is 8, local router ID is 192.168.1.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
              x best-external, a additional-path, c RIB-compressed,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
 *>i 192.168.1.1/32   10.0.0.1                      100      0 65441 i

Total number of prefixes 1


C1#show ip bgp
BGP table version is 10, local router ID is 192.168.1.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
              x best-external, a additional-path, c RIB-compressed,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
 *>i 192.168.1.1/32   10.0.0.1                      100      0 65441 i


C1#sh ip route
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2
       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
       ia - IS-IS inter area, * - candidate default, U - per-user static route
       o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP
       a - application route
       + - replicated route, % - next hop override

Gateway of last resort is not set

      10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        10.0.0.0/24 is directly connected, Ethernet0/0
L        10.0.0.3/32 is directly connected, Ethernet0/0
      192.168.1.0/32 is subnetted, 2 subnets
B        192.168.1.1 [200/0] via 10.0.0.1, 00:10:15
C        192.168.1.3 is directly connected, Loopback0

Log

*Jan 25 11:20:18.830: %BGP-5-ADJCHANGE: neighbor 10.0.0.1 Up
*Jan 25 11:20:18.838: BGP(0): 10.0.0.1 rcvd UPDATE w/ attr: nexthop 10.0.0.1, origin i, localpref 100, merged path 65441, AS_PATH
*Jan 25 11:20:18.838: BGP(0): 10.0.0.1 rcvd 192.168.1.1/32
*Jan 25 11:20:18.845: BGP(0): Revise route installing 1 of 1 routes for 192.168.1.1/32 -> 10.0.0.1(global) to main IP table

J2 sends the route to J1. No AS_PATH prepend is configured so the AS_PATH in the update is empty.

jhn@J2> show route advertising-protocol bgp 10.0.0.1 detail all

TEST.inet.0: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
* 192.168.1.2/32 (1 entry, 1 announced)
 BGP group IBGP type Internal
     Nexthop: Self
     Localpref: 100
     AS path: [65441] I Path Attribute - AS_PATH: empty
        Path Attribute - NEXT_HOP: 10.0.0.2 
        Path Attribute - LOCAL_PREF: 100
    Network Layer Reachability Information (NLRI)
        192.168.1.2/32
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 23
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 0

J1 accepts the route from J2. Notice the empty AS_PATH.

jhn@J1> show route receive-protocol bgp 10.0.0.2 detail all

__juniper_private1__.inet.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)

__juniper_private2__.inet.0: 1 destinations, 1 routes (0 active, 0 holddown, 1 hidden)

TEST.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
* 192.168.1.2/32 (1 entry, 1 announced)
     Accepted
     Nexthop: 10.0.0.2
     Localpref: 100
     AS path: I

__juniper_private1__.inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)


jhn@J1> show route

TEST.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 01:03:22
                    > via em0.0
10.0.0.1/32        *[Local/0] 02:52:47
                      Local via em0.0
192.168.1.1/32     *[Direct/0] 02:57:18
                    > via lo0.0
192.168.1.2/32     *[BGP/170] 01:02:54, localpref 100
                      AS path: I
                    > to 10.0.0.2 via em0.0
192.168.1.3/32     *[BGP/170] 00:08:44, MED 0, localpref 100
                      AS path: I
                    > to 10.0.0.3 via em0.0

C1 sends the route to J1 without prepending the AS_PATH although it is configured to do so. That’s Cisco’s approach to AS_PATH prepend in iBGP updates.

C1#show ip bgp neighbors 10.0.0.1 advertised-routes
BGP table version is 12, local router ID is 192.168.1.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
              x best-external, a additional-path, c RIB-compressed,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
 *>  192.168.1.3/32   0.0.0.0                  0         32768 i   

Total number of prefixes 1

Packet Capture

Frame 126: 110 bytes on wire (880 bits), 110 bytes captured (880 bits) on interface 0
Ethernet II, Src: aa:bb:cc:00:01:00 (aa:bb:cc:00:01:00), Dst: PcsCompu_75:c8:a3 (08:00:27:75:c8:a3)
Internet Protocol Version 4, Src: 10.0.0.3, Dst: 10.0.0.1
Transmission Control Protocol, Src Port: 15603, Dst Port: 179, Seq: 416, Ack: 286, Len: 56
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 56
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 28
    Path attributes
        Path Attribute - ORIGIN: IGP
        Path Attribute - AS_PATH: empty
        Path Attribute - NEXT_HOP: 10.0.0.3 
        Path Attribute - MULTI_EXIT_DISC: 0
        Path Attribute - LOCAL_PREF: 100
    Network Layer Reachability Information (NLRI)
        192.168.1.3/32
            NLRI prefix length: 32
            NLRI prefix: 192.168.1.3

J1 receives the route from C1.

jhn@J1> show route receive-protocol bgp 10.0.0.3 detail

TEST.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
* 192.168.1.3/32 (1 entry, 1 announced)
     Accepted
     Nexthop: 10.0.0.3
     MED: 0
     Localpref: 100
     AS path: I


jhn@J1> show route

TEST.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 01:03:22
                    > via em0.0
10.0.0.1/32        *[Local/0] 02:52:47
                      Local via em0.0
192.168.1.1/32     *[Direct/0] 02:57:18
                    > via lo0.0
192.168.1.2/32     *[BGP/170] 01:02:54, localpref 100
                      AS path: I
                    > to 10.0.0.2 via em0.0
192.168.1.3/32     *[BGP/170] 00:08:44, MED 0, localpref 100
                      AS path: I
                    > to 10.0.0.3 via em0.0

Conclusion

There is a significant difference in the way Cisco and Juniper deal with iBGP updates regarding the AS_PATH attribute. Junos respects the user configuration and prepends the local AS to the AS_PATH and lets the receiving router decide to accept or reject the update by applying the standard AS_PATH check. IOS silently ignores the AS_PATH prepend policy configured but, interestingly, does not apply the AS_PATH check on the iBGP updates.

Of course, AS_PATH prepending is not supposed to be used with iBGP. Local Preference should be the tool of choice to influence iBGP path selection, however it is interesting to see the different approach of each vendor.

Comments