jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 1 | .. _mplsfib: |
| 2 | |
| 3 | MPLS FIB |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 4 | -------- |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 5 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 6 | Implementation |
| 7 | ^^^^^^^^^^^^^^^ |
| 8 | |
| 9 | The MPLS FIB is implemented using exactly the same data structures as |
| 10 | the IP FIB. The only difference is the implementation of the |
| 11 | table. Whereas for IPv4 this is an mtrie and for IPv6 a hash table, |
| 12 | for MPLS it is a flat array indexed by a 21 bit key (label & EOS |
| 13 | bit). This implementation is chosen to favour packet forwarding speed. |
| 14 | |
Neale Ranns | dfd3954 | 2020-11-09 10:09:42 +0000 | [diff] [blame] | 15 | It can be the case in MPLS forwarding that packets received with the |
| 16 | EOS bit set in the MPLS label need to be forwarded differently from |
| 17 | those without. The most common example of this is if the path set |
| 18 | contains a path that does not have an output label. In this case the |
| 19 | non-EOS packets cannot take this path, because to do so would expose |
| 20 | the neighbouring router to a label that it did not allocate. |
| 21 | |
| 22 | The desgin choice to make with an MPLS FIB table is therefore: |
| 23 | - 20 bit key: label only. When the EOS and non-EOS actions differ the result is a 'EOS-choice' object. |
| 24 | - 21 bit key: label and EOS-bit. The result is then the specific action based on EOS-bit. |
| 25 | |
| 26 | 20 bit key |
| 27 | - Advantages:lower memory overhead, since there are few DB entries. |
| 28 | - Disadvantages: slower DP performance in the case the path-lists |
| 29 | differ, as more objects are encounterd in the switch path |
| 30 | |
| 31 | 21 bit key |
| 32 | - Advantages: faster DP performance |
| 33 | Disadvantages: increased memory footprint. |
| 34 | |
| 35 | Switching between schemes based on observed/measured action similarity |
| 36 | is not considered on the grounds of complexity and flip-flopping. |
| 37 | |
| 38 | VPP mantra - favour performance over memory. We choose a 21 bit key. |
| 39 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 40 | Basics |
| 41 | ^^^^^^ |
| 42 | |
| 43 | MPLS is not enabled by default. There are two steps to get |
| 44 | started. First, create the default MPLS FIB: |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 45 | |
| 46 | .. code-block:: console |
| 47 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 48 | $ mpls table add 0 |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 49 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 50 | With '0' being the magic number for the 'default' table (just like it |
| 51 | is for IPv[46]). One can create other MPLS tables, but, unlike IP |
| 52 | tables, one cannot 'bind' non-default MPLS tables to interfaces, in |
| 53 | other words all MPLS packets received on an interface will always |
| 54 | result in a lookup in the default table. One has to be more inventive |
| 55 | to use the non-default tables... |
| 56 | |
| 57 | Secondly, for *each* interface on which you wish to *receive* MPLS |
| 58 | packets, that interface must be MPLS 'enabled' |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 59 | |
| 60 | .. code-block:: console |
| 61 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 62 | $ set interface mpls GigEthernet0/0/0 enable |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 63 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 64 | there is no equivalent enable for transmit, all that is required is to |
| 65 | use an interface as an egress path. |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 66 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 67 | Entries in the MPLS FIB can be displayed with: |
| 68 | |
| 69 | .. code-block:: console |
| 70 | |
| 71 | $ sh mpls fib [table X] [label] |
| 72 | |
| 73 | There is a tight coupling between IP and MPLS forwarding. MPLS |
| 74 | forwarding equivalence classes (FECs) are often an IP prefix – that is |
| 75 | to say that traffic matching a given IP prefix is routed into a MPLS |
Neale Ranns | dfd3954 | 2020-11-09 10:09:42 +0000 | [diff] [blame] | 76 | label switch path (LSP). It is thus necessary to be able to associate |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 77 | a given prefix/route with an [out-going] MPLS label that will be |
| 78 | imposed when the packet is forwarded. This is configured as: |
| 79 | |
| 80 | .. code-block:: console |
| 81 | |
| 82 | $ ip route add 1.1.1.1/32 via 10.10.10.10 GigEthernet0/0/0 out-labels 33 |
| 83 | |
| 84 | packets matching 1.1.1.1/32 will be forwarded out GigEthernet0/0/0 and have |
| 85 | MPLS label 33 imposed. More than one out-going label can be |
| 86 | specified. Out-going MPLS labels can be applied to recursive and |
| 87 | non-recursive routes, e.g; |
| 88 | |
| 89 | .. code-block:: console |
| 90 | |
| 91 | $ ip route add 2.2.2.0/24 via 1.1.1.1 out-labels 34 |
| 92 | |
| 93 | packets matching 2.2.2.0/24 will thus have two MPLS labels imposed; 34 |
| 94 | and 33. This is the realisation of, e,g, an MPLS BGP VPNv4. |
| 95 | |
| 96 | To associate/allocate a local-label for a prefix, and thus have |
| 97 | packets to that local-label forwarded equivalently to the prefix do; |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 98 | |
| 99 | .. code-block:: console |
| 100 | |
| 101 | $ mpls local-label 99 2.2.2.0/24 |
| 102 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 103 | In the API this action is called a ‘bind’. |
| 104 | The router receiving the MPLS encapsulated packets needs to be |
| 105 | programmed with actions associated which each label value – this is |
Neale Ranns | dfd3954 | 2020-11-09 10:09:42 +0000 | [diff] [blame] | 106 | the role of the MPLS FIB. The MPLS FIB is a table, whose key is the |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 107 | MPLS label value and end-of-stack (EOS) bit, which stores the action |
| 108 | to perform on packets with matching encapsulation. Currently supported |
| 109 | actions are: |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 110 | |
| 111 | #. Pop the label and perform an IPv[46] lookup in a specified table |
| 112 | #. Pop the label and forward via a specified next-hop (this is penultimate-hop-pop, PHP) |
| 113 | #. Swap the label and forward via a specified next-hop. |
| 114 | |
| 115 | These can be programmed respectively by: |
| 116 | |
Neale Ranns | 995ff06 | 2018-12-06 08:36:55 -0800 | [diff] [blame] | 117 | .. code-block:: console |
| 118 | |
| 119 | $ mpls local-label 33 eos ip4-lookup-in-table X |
| 120 | $ mpls local-label 33 [eos] via 10.10.10.10 GigEthernet0/0/0 |
| 121 | $ mpls local-label 33 [eos] via 10.10.10.10 GigEthernet0/0/0 out-labels 66 |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 122 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 123 | the latter is an example of an MPLS cross connect. Any description of |
| 124 | a next-hop, recursive, non-recursive, labelled, non-labelled, etc, |
| 125 | that is valid for an IP prefix, is also valid for an MPLS |
| 126 | local-label. Note the use of the 'eos' keyword which indicates the |
| 127 | programming is for the case when the label is end-of-stack. The last |
| 128 | two operations can apply to both eos and non-eos packets, but the pop |
| 129 | and IP lookup only to an eos packet. |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 130 | |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 131 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 132 | MPLS VPN |
| 133 | ^^^^^^^^ |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 134 | |
Neale Ranns | dfd3954 | 2020-11-09 10:09:42 +0000 | [diff] [blame] | 135 | To configure an MPLS VPN for a PE the following example can be used. |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 136 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 137 | Step 1; Configure routes to the iBGP peers - note these route MUST |
| 138 | have out-going labels; |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 139 | |
| 140 | .. code-block:: console |
| 141 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 142 | $ ip route add 10.0.0.1/32 via 192.168.1.2 Eth0 out-labels 33 |
| 143 | $ ip route add 10.0.0.2/32 via 192.168.2.2 Eth0 out-labels 34 |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 144 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 145 | Step 2; Configure the customer 'VRF' |
jdenisco | 0923a23 | 2018-08-29 13:19:43 -0400 | [diff] [blame] | 146 | |
Neale Ranns | 75c276f | 2018-08-31 00:45:19 -0700 | [diff] [blame] | 147 | .. code-block:: console |
| 148 | |
| 149 | $ ip table add 2 |
| 150 | |
| 151 | Step 3; add a route via the iBGP peer[s] with the MPLS label |
| 152 | advertised by that peer |
| 153 | |
| 154 | .. code-block:: console |
| 155 | |
| 156 | $ ip route add table 2 10.10.10.0/24 via 10.0.0.2 next-hop-table 0 out-label 122 |
| 157 | $ ip route add table 2 10.10.10.0/24 via 10.0.0.1 next-hop-table 0 out-label 121 |
| 158 | |
| 159 | Step 4; add a route via the eBGP peer |
| 160 | |
| 161 | .. code-block:: console |
| 162 | |
| 163 | $ ip route add table 2 10.10.20.0/24 via 172.16.0.1 next-hop-table 2 |
| 164 | |
| 165 | Step 5; depending on the label allocation scheme used, add routes to |
| 166 | the MPLS FIB to accept incoming labelled packets: |
| 167 | |
| 168 | #. per-prefix label scheme - this command 'binds' the label to the same |
| 169 | forwarding as the IP route |
| 170 | |
| 171 | .. code-block:: console |
| 172 | |
| 173 | $ mpls local-label 99 10.10.20.0/24 |
| 174 | |
| 175 | #. per-CE label scheme - this pops the incoming label and forwards via |
| 176 | the next-hop provided. Append config for 'out-labels' if so desired. |
| 177 | |
| 178 | .. code-block:: console |
| 179 | |
| 180 | $ mpls local-label 99 via 172.16.0.1 next-hop-table 2 |
| 181 | |
| 182 | #. per-VRF label scheme |
| 183 | |
| 184 | .. code-block:: console |
| 185 | |
| 186 | $ mpls local-label 99 via ip4-lookup-in-table 2 |
| 187 | |
| 188 | MPLS Tunnels |
| 189 | ^^^^^^^^^^^^ |
| 190 | |
| 191 | MPLS tunnels are unidirectional and can impose a stack of labels. They |
| 192 | are 'normal' interfaces and thus can be used, for example, as the |
| 193 | target for IP routes and L2 cross-connects. To construct a tunnel: |
| 194 | |
| 195 | .. code-block:: console |
| 196 | |
| 197 | $ mpls tunnel add via 10.10.10.10 GigEthernet0/0/0 out-labels 33 44 55 |
| 198 | |
| 199 | and to then have that created tunnel to perform ECMP: |
| 200 | |
| 201 | .. code-block:: console |
| 202 | |
| 203 | $ mpls tunnel add mpls-tunnel0 via 10.10.10.11 GigEthernet0/0/0 out-labels 66 77 88 |
| 204 | |
| 205 | use |
| 206 | |
| 207 | .. code-block:: console |
| 208 | |
| 209 | $ sh mpls tunnel [X] |
| 210 | |
| 211 | to see the monster you have created. |
| 212 | |
| 213 | An MPLS tunnel interface is an interface like any other and now ready |
| 214 | for use with the usual set of interface commands, e.g.: |
| 215 | |
| 216 | .. code-block:: console |
| 217 | |
| 218 | $ set interface state mpls-tunnel0 up |
| 219 | $ set interface ip address mpls-tunnel0 192.168.1.1/30 |
| 220 | $ ip route 1.1.1.1/32 via mpls-tunnel0 |