MPLS/RSVP and BGP L3VPN #4

This post is the 4th post of my MPLS series. You can find the first three here: #1, #2 , #3
In an MPLS network, PE routers keep the site specific VPN routes inside VRF (Virtual Routing and Forwarding) tables and send the routes that they learned from CE routers to remote PE routers by using MP-BGP (Multiprotocol BGP). LSPs we have configured so far will be used to send our L3VPN traffic.
One of the greatest things that VRF along with MP-BGP is that in your PE router you can keep the same network addresses in different sites and completely isolated from each other.

mpls_ospf_rsvp

I will setup a BGP-L3VPN between CustC (10.10.10.0/24) and CustA (10.20.20.0/24)

I can start configuring VRF tables on both sides. VRF is a simple routing instance in a junos box but its instance type is vrf. For simplicity I won’t configure BGP between CE and PE routers but you can also do that.

Lets configure the first VRF instance on J40 router for CustC

CustC VRF Configuration

[edit routing-instances]
root@j40# show 
vpn-CustC {
    instance-type vrf;
    interface ge-0/0/2.0;
    route-distinguisher 2001:10;
    vrf-target {
        import target:8000:100;
        export target:8000:100;
    }
    vrf-table-label;
}

[edit]
root@j40# show interfaces ge-0/0/2 
unit 0 {
    family inet {
        address 98.1.1.1/24;
    }
}

Some configuration items on this VRF instance require some explanation;

interface ge-0/0/2.0: This is the gigabit interface which provides connection to this multiaccess network CustC is also part of it.

route-distinguisher: This is used to identify the routes sent by this particular VPN and each instance must have its own

unique route-distinguisher. Note that it is unique. It must be different in all instances in the PE router.

vrf-target: With import statement any route received with this target (i.e exported from other PE router) will be put into CustC.inet.0 table. Export statement does the reverse. It advertises all routes in CustC.inet.0 table with 8000:100 tag. If we speak specifically for this CustC and CustA L3VPN connection, route targets must be the same in both sides.

vrf-table-label: You can visit the address here for this statement as well. As I have a multiaccess network, I need to enable this statement without which I am unable to send my VRF routes.

CustA VRF Configuration

[edit routing-instances]
root@j35# show 
vpn-CustA {
    instance-type vrf;
    interface ge-0/0/2.0;
    route-distinguisher 2001:20;
    vrf-target target:8000:100;
    vrf-table-label;
}

Note: You can note the difference in vrf-target single line statement. For this setup, it also works.

We configured VRFs but we haven’t shared these routes between PE routers J35 and J40. For this, we must modify BGP configuration at both side and enable family inet and inet-vpn.

[edit protocols bgp]
root@j40# show 
group int {
    type internal;
    local-address 10.1.1.8;
    family inet {
        unicast;
    }
    family inet-vpn {
        unicast;
    }
    export my-nets;
    neighbor 10.1.1.7;
}

[edit protocols bgp]
root@j35# show 
group int {
    type internal;
    local-address 10.1.1.7;
    family inet {
        unicast;
    }
    family inet-vpn {
        unicast;
    }
    export bgp-my-nets;
    neighbor 10.1.1.8;
}

At both sides, required configuration is done. Now lets see how our routing tables look like.

J40

root@j40> show route table bgp.l3vpn.0

bgp.l3vpn.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2001:20:12.1.1.0/24                
                   *[BGP/170] 00:55:33, localpref 100, from 10.1.1.7
                      AS path: I
                    > to 25.1.2.1 via ge-0/0/1.0, label-switched-path j40-to-j35
                      to 24.1.1.1 via ge-0/0/0.0, label-switched-path j40-to-j35

If you take a look at this VPN-IPV4 route (2001:10:12.1.1.0/24), you can see that is prefixed by “2001:20” which is the route-distinguisher we configured on J35.

J35

root@j35> show route table bgp.l3vpn.0     

bgp.l3vpn.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2001:10:98.1.1.0/24                
                   *[BGP/170] 00:54:57, localpref 100, from 10.1.1.8
                      AS path: I
                    > to 172.41.1.1 via ge-0/0/1.0, label-switched-path j35-to-j40
                      to 172.40.1.1 via ge-0/0/0.0, label-switched-path j35-to-j40

Routing table bgp.l3vpn.0 contains all VPN routers received from other PE routers and based on the vrf-target, route is installed into the respective VRF. Let’s check how routes are installed in VRF instances.

VRF route tables

root@j40> show route table vpn-CustC.inet.0 

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

12.1.1.0/24        *[BGP/170] 01:04:13, localpref 100, from 10.1.1.7
                      AS path: I
                    > to 25.1.2.1 via ge-0/0/1.0, label-switched-path j40-to-j35
                      to 24.1.1.1 via ge-0/0/0.0, label-switched-path j40-to-j35
98.1.1.0/24        *[Direct/0] 01:22:36
                    > via ge-0/0/2.0
98.1.1.1/32        *[Local/0] 01:22:36
                      Local via ge-0/0/2.0

[edit]
root@j35# exit 
Exiting configuration mode

root@j35> show route table vpn-CustA.inet.0 

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

12.1.1.0/24        *[Direct/0] 01:21:17
                    > via ge-0/0/2.0
12.1.1.1/32        *[Local/0] 01:21:17
                      Local via ge-0/0/2.0
98.1.1.0/24        *[BGP/170] 01:03:22, localpref 100, from 10.1.1.8
                      AS path: I
                    > to 172.41.1.1 via ge-0/0/1.0, label-switched-path j35-to-j40
                      to 172.40.1.1 via ge-0/0/0.0, label-switched-path j35-to-j40

As you can see, network 12.1.1.0/24 from J35 is now available in J40’s VRF table as a BGP route and 98.1.1.0/24 from J40 is now available in J35’s VRF table.

In the beginning of the post I mentioned that CustC has 10.10.10.0/24) and CustA has 10.20.20.0/24 networks. Let’s distribute these as well by static routes:

root@j40# set routing-instances vpn-CustC routing-options static route 10.10.10.0/24 next-hop 98.1.1.2
root@j35# set routing-instances vpn-CustA routing-options static route 10.20.20.0/24 next-hop 12.1.1.2 

root@j35> show route table vpn-CustA.inet.0 

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

10.10.10.0/24      *[BGP/170] 00:00:51, localpref 100, from 10.1.1.8
                      AS path: I
                    > to 172.41.1.1 via ge-0/0/1.0, label-switched-path j35-to-j40
                      to 172.40.1.1 via ge-0/0/0.0, label-switched-path j35-to-j40
10.20.20.0/24      *[Static/5] 00:00:09
                    > to 12.1.1.2 via ge-0/0/2.0
12.1.1.0/24        *[Direct/0] 01:27:19
                    > via ge-0/0/2.0
12.1.1.1/32        *[Local/0] 01:27:19
                      Local via ge-0/0/2.0
98.1.1.0/24        *[BGP/170] 01:09:24, localpref 100, from 10.1.1.8
                      AS path: I
                    > to 172.41.1.1 via ge-0/0/1.0, label-switched-path j35-to-j40
                      to 172.40.1.1 via ge-0/0/0.0, label-switched-path j35-to-j40


root@j40> show route table vpn-CustC.inet.0 

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

10.10.10.0/24      *[Static/5] 00:01:02
                    > to 98.1.1.2 via ge-0/0/2.0
10.20.20.0/24      *[BGP/170] 00:00:21, localpref 100, from 10.1.1.7
                      AS path: I
                    > to 25.1.2.1 via ge-0/0/1.0, label-switched-path j40-to-j35
                      to 24.1.1.1 via ge-0/0/0.0, label-switched-path j40-to-j35
12.1.1.0/24        *[BGP/170] 01:11:35, localpref 100, from 10.1.1.7
                      AS path: I
                    > to 25.1.2.1 via ge-0/0/1.0, label-switched-path j40-to-j35
                      to 24.1.1.1 via ge-0/0/0.0, label-switched-path j40-to-j35
98.1.1.0/24        *[Direct/0] 01:29:58
                    > via ge-0/0/2.0
98.1.1.1/32        *[Local/0] 01:29:58

As you can see again, new static routes are sent via MP-BGP and installed on VRF tables. By using this technique, you can have lots of customers who are using the same network without having any duplicate network address issue.

Last but not least I would like to show how an MPLS frame looks like on the way and just before the PE router.

I did a test by sending a single PING from J36 router towards 10.10.10.1 address. It is tunneled across the L3VPN that I configured. What I am interested is how the frame looks like on two links.

  • Between J33-J32
  • After J32
  • Between J33-J32
    label_stack_mpls

    If you look carefully at this frame which I captured before it arrives at J32, you see that it has dual label. Outer label is 299762 as expected from the output from RSVP session command below and the inner label is 17. We will see why it is 17 below;

    root@J32> show rsvp session 
    Ingress RSVP: 0 sessions
    Total 0 displayed, Up 0, Down 0
    
    Egress RSVP: 0 sessions
    Total 0 displayed, Up 0, Down 0
    
    Transit RSVP: 2 sessions
    To              From            State   Rt Style Labelin Labelout LSPname 
    10.1.1.7        10.1.1.8        Up       0  1 FF  299776   299776 j40-to-j35
    10.1.1.8        10.1.1.7        Up       0  1 FF  299792        3 j35-to-j40
    Total 2 displayed, Up 2, Down 0
    

    After J32

    l3vpn_popped_label

    This frame has been captured just before it arrives at J40. J32 removed the outer label as it does PHP. If you take a look at mpls table of J40, you can see that it sends any MPLS frame having 17 label to vpn-CustC.inet.0 table after popping it. If you asked me how does J35 knows this label 17, I can say that they share this label during MP-BGP route exchange.

    root@j40> show route table mpls.0 
    
    mpls.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
    + = Active Route, - = Last Active, * = Both
    
    0                  *[MPLS/0] 03:12:52, metric 1
                          Receive
    1                  *[MPLS/0] 03:12:52, metric 1
                          Receive
    2                  *[MPLS/0] 03:12:52, metric 1
                          Receive
    13                 *[MPLS/0] 03:12:52, metric 1
                          Receive
    17                 *[VPN/0] 02:15:49
                          to table vpn-CustC.inet.0, Pop   
    

    I hope this post was useful to explain BGP L3VPN in junos. I have tried to be as simple as possible for my future readings as well:)

    If I can I would like to add one more post in which I can use flow mode SRX with MPLS but it is a bit more complex setup than this one. I will see when I can get round to it.

    Stay tuned!

    About: rtoodtoo

    Genco has worked for more than 10 years as a Network/Support Engineer. He is also interested in Python, Linux, Security and SD-WAN, currently lives in the Netherlands and works as a Network Support Engineer at Tesla Inc. // JNCIE-SEC #223 / RHCE / PCNSE


    2 thoughts on “MPLS/RSVP and BGP L3VPN #4”

    You have a feedback?

    This site uses Akismet to reduce spam. Learn how your comment data is processed.