Understanding BGP Labeled Unicast

      2 Comments on Understanding BGP Labeled Unicast

We’ve talked in previous posts on how we can use LDP and RSVP as label distribution protocols. Without LDP and RSVP – we wouldn’t be able to easily create LSPs which means we’d have to do it manually as we did in my first post on MPLS. That being said – the discussion around MPLS label distribution usually focuses around these two protocols, but you might (or might not depending on how long you’ve been in networking) be surprised to learn that we can also use BGP to advertise labels. That is – we can build end to end LSPs without the use of LDP or RSVP. Using BGP for label distribution comes with it’s own set of requirements (and associated oddities) so in this post we’ll talk through the use case.

Advertising labels through BGP is something that we’ve seen before. Specifically, we saw it in the MPLS VPN use case where PE routers advertise a VPN label so that the remote PE knows what VRF/VPN the traffic belongs in. In that use case, we did a BGP peering with the inet-vpn address family. To do BGP labeled unicast (commonly called BGP-LU) we do a BGP peering with the labeled-unicast address family. The labeled-unicast address family in AFI/SAFI parlance it would be AFI 1 and SAFI 4. Before we get too far ahead of ourselves, let’s setup a lab so we can see all of this in action. Our lab topology will look like this…

Note: The blue numbers indicate interface numbers. AKA – 0 = ge-0/0/0 etc. I’ve included all of the detail in this diagram but will take it out in subsequent ones because it gets too cluttered so use this for reference if needed.

As you can see, we have 7 routers connected in serial with the end or tail routers each hosting a remote subnet. vMX1 hosts 10.10.10.0/24 and vMX7 hosts 192.168.10.0/24. Our base configuration only defines interface IP addresses so at this point a host in 10.10.10.0/24 can not reach a host in 192.168.10.0/24. I’ll post the base configuration so we’re all on the same page…

vMX1

set interfaces ge-0/0/0 unit 0 family inet address 10.10.10.1/24
set interfaces ge-0/0/1 unit 0 family inet address 169.254.10.0/31
set interfaces ge-0/0/1 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 1.1.1.1/32 primary

vMX2

set interfaces ge-0/0/0 unit 0 family inet address 169.254.10.1/31
set interfaces ge-0/0/1 unit 0 family inet address 169.254.10.2/31
set interfaces ge-0/0/0 unit 0 family mpls
set interfaces ge-0/0/1 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 2.2.2.2/32 primary

vMX3

set interfaces ge-0/0/0 unit 0 family inet address 169.254.10.3/31
set interfaces ge-0/0/1 unit 0 family inet address 169.254.10.4/31
set interfaces ge-0/0/0 unit 0 family mpls
set interfaces ge-0/0/1 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 3.3.3.3/32 primary

vMX4

set interfaces ge-0/0/0 unit 0 family inet address 169.254.10.5/31
set interfaces ge-0/0/1 unit 0 family inet address 169.254.10.6/31
set interfaces ge-0/0/0 unit 0 family mpls
set interfaces ge-0/0/1 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 4.4.4.4/32 primary

vMX5

set interfaces ge-0/0/0 unit 0 family inet address 169.254.10.7/31
set interfaces ge-0/0/1 unit 0 family inet address 169.254.10.8/31
set interfaces ge-0/0/0 unit 0 family mpls
set interfaces ge-0/0/1 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 5.5.5.5/32 primary

vMX6

set interfaces ge-0/0/0 unit 0 family inet address 169.254.10.9/31
set interfaces ge-0/0/1 unit 0 family inet address 169.254.10.10/31
set interfaces ge-0/0/0 unit 0 family mpls
set interfaces ge-0/0/1 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 6.6.6.6/32 primary

vMX7

set interfaces ge-0/0/0 unit 0 family inet address 169.254.10.11/31
set interfaces ge-0/0/1 unit 0 family inet address 192.168.10.1/24
set interfaces ge-0/0/0 unit 0 family mpls
set interfaces lo0 unit 0 family inet no-redirects
set interfaces lo0 unit 0 family inet address 7.7.7.7/32 primary

Let’s add in some BGP configuration on each of the routers so we can start exchanging some routing information…

vMX1

set routing-options router-id 1.1.1.1
set routing-options autonomous-system 65001
set protocols bgp group external type external
set protocols bgp group external family inet labeled-unicast
set protocols bgp group external peer-as 65002
set protocols bgp group external neighbor 169.254.10.1

vMX2

set routing-options router-id 2.2.2.2
set routing-options autonomous-system 65002
set protocols bgp group external-1 type external
set protocols bgp group external-1 peer-as 65001
set protocols bgp group external-1 family inet labeled-unicast
set protocols bgp group external-1 neighbor 169.254.10.0
set protocols bgp group external-2 type external
set protocols bgp group external-2 peer-as 65003
set protocols bgp group external-2 family inet labeled-unicast
set protocols bgp group external-2 neighbor 169.254.10.3

vMX3

set routing-options router-id 3.3.3.3
set routing-options autonomous-system 65003
set protocols bgp group external-1 type external
set protocols bgp group external-1 peer-as 65002
set protocols bgp group external-1 family inet labeled-unicast
set protocols bgp group external-1 neighbor 169.254.10.2
set protocols bgp group external-2 type external
set protocols bgp group external-2 peer-as 65004
set protocols bgp group external-2 family inet labeled-unicast
set protocols bgp group external-2 neighbor 169.254.10.5

vMX4

set routing-options router-id 4.4.4.4
set routing-options autonomous-system 65004
set protocols bgp group external-1 type external
set protocols bgp group external-1 peer-as 65003
set protocols bgp group external-1 family inet labeled-unicast
set protocols bgp group external-1 neighbor 169.254.10.4
set protocols bgp group external-2 type external
set protocols bgp group external-2 peer-as 65005
set protocols bgp group external-2 family inet labeled-unicast
set protocols bgp group external-2 neighbor 169.254.10.7

vMX5

set routing-options router-id 5.5.5.5
set routing-options autonomous-system 65005
set protocols bgp group external-1 type external
set protocols bgp group external-1 peer-as 65004
set protocols bgp group external-1 family inet labeled-unicast
set protocols bgp group external-1 neighbor 169.254.10.6
set protocols bgp group external-2 type external
set protocols bgp group external-2 peer-as 65006
set protocols bgp group external-2 family inet labeled-unicast
set protocols bgp group external-2 neighbor 169.254.10.9

vMX6

set routing-options router-id 6.6.6.6
set routing-options autonomous-system 65006
set protocols bgp group external-1 type external
set protocols bgp group external-1 peer-as 65005
set protocols bgp group external-1 family inet labeled-unicast
set protocols bgp group external-1 neighbor 169.254.10.8
set protocols bgp group external-2 type external
set protocols bgp group external-2 peer-as 65007
set protocols bgp group external-2 family inet labeled-unicast
set protocols bgp group external-2 neighbor 169.254.10.11

vMX7

set routing-options router-id 7.7.7.7
set routing-options autonomous-system 65007
set protocols mpls interface ge-0/0/0.0
set protocols bgp group external type external
set protocols bgp group external family inet labeled-unicast
set protocols bgp group external peer-as 65006
set protocols bgp group external neighbor 169.254.10.10

Alright – so at this point, we should have BGP peering from end to end…

You’ll notice that each BGP peering was an eBGP peering – we’ll talk through why that is important later on. You’ll also notice that we’ve peered in the inet labeled-unicast address family rather than the normal inet unicast family. At this point, we’re not doing anything interesting with the BGP peering since we’re not exporting any prefixes. Let’s export the loopback address into BGP for each tail router (vMX1 and vMX7)…

vMX1

set policy-options prefix-list local-prefixes 1.1.1.1/32 
set policy-options policy-statement local-prefixes from protocol direct  
set policy-options policy-statement local-prefixes from prefix-list local-prefixes    
set policy-options policy-statement local-prefixes then accept                    
set protocols bgp group external export local-prefixes 

vMX7

set policy-options prefix-list local-prefixes 7.7.7.7/32 
set policy-options policy-statement local-prefixes from protocol direct  
set policy-options policy-statement local-prefixes from prefix-list local-prefixes    
set policy-options policy-statement local-prefixes then accept                    
set protocols bgp group external export local-prefixes 

With the above configuration, each tail router should be advertising their loopback into BGP. Each other router will get the advertisement and pass it along to the next router across it’s eBGP peering to the upstream router. If we look at the advertisement for 7.7.7.7/32 that we’re getting on vMX1 – we’ll see this…

[email protected]> show route table inet.0 7.7.7.7/32 

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

7.7.7.7/32         *[BGP/170] 00:01:02, localpref 100
                      AS path: 65002 65003 65004 65005 65006 65007 I, validation-state: unverified
                    > to 169.254.10.1 via ge-0/0/1.0, Push 300144

[email protected]> 

Whoa! The router now has a label operation associated with reaching 7.7.7.7/32. In this case, vMX1 will push label 300144 onto the frame to reach the destination. And if we try a ping from vMX1’s loopback to vMX7’s loopback…

[email protected]> ping 7.7.7.7 source 1.1.1.1 count 3 
PING 7.7.7.7 (7.7.7.7): 56 data bytes
64 bytes from 7.7.7.7: icmp_seq=0 ttl=59 time=12.458 ms
64 bytes from 7.7.7.7: icmp_seq=1 ttl=59 time=3.620 ms
64 bytes from 7.7.7.7: icmp_seq=2 ttl=59 time=5.695 ms

--- 7.7.7.7 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 3.620/7.258/12.458/3.774 ms

[email protected]> 

It works! If we’re questioning whether or not this actually works we can do a packet capture on the link between vMX1 and vMX2…

Note: You might have caught that we only enabled the MPLS family on the interfaces themselves during the initial configuration. We didn’t enable the interfaces under the MPLS protocol stanza. Doing so is not required at this point since we’re not using an MPLS control plane protocol like RSVP.

Let’s now also advertise our “customer” subnets into BGP by adding them to the local-prefixes prefix list on each tail router…

vMX1

set policy-options prefix-list local-prefixes 10.10.10.0/24

vMX7

set policy-options prefix-list local-prefixes 192.168.10.0/24

Now our customer pings should work as well…

[email protected]_client:~# ping 192.168.10.100 -c 5
PING 192.168.10.100 (192.168.10.100) 56(84) bytes of data.
64 bytes from 192.168.10.100: icmp_seq=1 ttl=57 time=4.55 ms
64 bytes from 192.168.10.100: icmp_seq=2 ttl=57 time=5.11 ms
64 bytes from 192.168.10.100: icmp_seq=3 ttl=57 time=4.88 ms
64 bytes from 192.168.10.100: icmp_seq=4 ttl=57 time=5.55 ms
64 bytes from 192.168.10.100: icmp_seq=5 ttl=57 time=3.95 ms

--- 192.168.10.100 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 3.955/4.812/5.553/0.539 ms
[email protected]_client:~# 

And if we look at our routing table we’ll see the same thing that we saw for 7.7.7.7/32

[email protected]> show route table inet.0 192.168.10.0/24 

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

192.168.10.0/24    *[BGP/170] 00:03:27, localpref 100
                      AS path: 65002 65003 65004 65005 65006 65007 I, validation-state: unverified
                    > to 169.254.10.1 via ge-0/0/1.0, Push 300144

[email protected]> 

So it would appear that we’re using an LSP to reach prefixes directly connected to vMX7’s. So let’s back up a second and think this through. How is this working? If you recall from our previous intro to MPLS posts the means for us to get into an MPLS LSP was typically through the use of the inet.3 table. That is, LDP or RSVP would generate entries for us in inet.3 which we would then be used by BGP as a part of a recursive lookup. For example, a remote router might have advertised us a destination of 192.168.127.0/24 with a next hop of 9.9.9.9. Since 9.9.9.9 is not directly connected, the router would do a recursive lookup on the prefix and find a matching entry in inet.3 which would be our entry point into an MPLS LSP. So since we’re clearly entering an LSP here – we should have entries in the inet.3 table right?…

[email protected]> show route table inet.3 

[email protected]> 

Wrong. And this is where things begin to get a little sticky. When I began learning about MPLS on the Juniper platform the use of the inet.3 made such great sense to me. If it had to be the entry point for all LSPs, then in my mind I had a clear definition of how this all worked. To make matters worse, there are lots and lots and lots of things you’ll read out there that say that the inet.3 table MUST be the entry point for all MPLS LSPs. That statement, while not accurate, is not entirely misguided. It is the place where LSPs endpoints formed by LDP and RSVP (the two leading label distribution protocols) do live. But BGP-LU presents a new a paradigm for us to deal with. And this wording from a Juniper doc is the best way to put it…

When BGP resolves a next-hop prefix, it examines both the inet.0 and inet.3 routing tables, seeking the next hop with the lowest preference. If it finds a next-hop entry with an equal preference in both routing tables, BGP prefers the entry in the inet.3 routing table.

In other words, if we had an LSP formed by either RSVP or LDP – it would most certainly win since our route preference for the BGP route is 170. So it seems that by using BGP-LU we can create MPLS LSPs simply through the use of BGP. But let’s back up a second and look at what’s going on. Let’s make a slight change on vMX3, vMX4, vMX5, and vMX6 to illustrate the point…

vMX3

delete protocols bgp group external-2 
set protocols bgp group internal-1 type internal
set protocols bgp group internal-1 family inet labeled-unicast
set protocols bgp group internal-1 peer-as 65003
set protocols bgp group internal-1 neighbor 4.4.4.4
set protocols bgp group internal-1 local-address 3.3.3.3
set protocols ospf area 0.0.0.0 interface ge-0/0/1
set protocols ospf area 0.0.0.0 interface lo0

vMX4

delete protocols bgp group external-1
delete protocols bgp group external-2 
set routing-options autonomous-system 65003
set protocols bgp group internal-1 type internal
set protocols bgp group internal-1 family inet labeled-unicast
set protocols bgp group internal-1 peer-as 65003
set protocols bgp group internal-1 neighbor 3.3.3.3
set protocols bgp group internal-1 neighbor 5.5.5.5
set protocols bgp group internal-1 local-address 4.4.4.4
set protocols bgp group internal-1 cluster 0.0.0.0 
set protocols ospf area 0.0.0.0 interface ge-0/0/0
set protocols ospf area 0.0.0.0 interface ge-0/0/1
set protocols ospf area 0.0.0.0 interface lo0

vMX5

delete protocols bgp group external-1
set routing-options autonomous-system 65003
set protocols bgp group internal-1 type internal
set protocols bgp group internal-1 family inet labeled-unicast
set protocols bgp group internal-1 peer-as 65003
set protocols bgp group internal-1 neighbor 4.4.4.4
set protocols bgp group internal-1 local-address 5.5.5.5
set protocols ospf area 0.0.0.0 interface ge-0/0/0
set protocols ospf area 0.0.0.0 interface lo0

vMX6

set protocols bgp group external-1 peer-as 65003

Ok – I lied – that’s not a small change at all. What we’ve done is changed the lab topology to look like this…

We’ve broken up our chain of eBGP peers and turned vMX3, vMX4, and vMX5 into their own little autonomous system. This AS (65003) then peers with AS 65002 on the left side and 65006 on the right side. In making this change, we should see no change in the advertisements being received on both tail routers. That is, vMX1 is still getting vMX7’s loopback as well as it’s client subnet…

[email protected]> show route table inet.0 protocol bgp 

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

7.7.7.7/32         *[BGP/170] 00:00:19, localpref 100
                      AS path: 65002 65003 65006 65007 I, validation-state: unverified
                    > to 169.254.10.1 via ge-0/0/1.0, Push 300272
192.168.10.0/24    *[BGP/170] 00:00:19, localpref 100
                      AS path: 65002 65003 65006 65007 I, validation-state: unverified
                    > to 169.254.10.1 via ge-0/0/1.0, Push 300272

[email protected]> 

And we should see the same on vMX7 which is receiving vMX1’s loopback and client subnet through BGP…

[email protected]> show route table inet.0 protocol bgp 

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

1.1.1.1/32         *[BGP/170] 00:00:53, localpref 100
                      AS path: 65006 65003 65002 65001 I, validation-state: unverified
                    > to 169.254.10.10 via ge-0/0/0.0, Push 300320
10.10.10.0/24      *[BGP/170] 00:00:53, localpref 100
                      AS path: 65006 65003 65002 65001 I, validation-state: unverified
                    > to 169.254.10.10 via ge-0/0/0.0, Push 300320

[email protected]> 

But if we look – we’ll notice that our clients can no longer ping each other….

[email protected]_client:~# ping 192.168.10.100 -c 3
PING 192.168.10.100 (192.168.10.100) 56(84) bytes of data.

--- 192.168.10.100 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 1999ms
[email protected]_client:~# 

So what’s going on? All of the routes are still where they should be and it looks to me like they all have label actions associated with them as we expected before. Let’s dig in and see what we can find.

On vMX1 it’s being told by vMX2 to use a label of 300272 to reach the right client subnet (and the loopback for that matter). So let’s see what vMX2 will do with this label…

[email protected]> show route table mpls.0 label 300272 

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

300272             *[VPN/170] 00:04:30
                    > to 169.254.10.3 via ge-0/0/1.0, Swap 300320

[email protected]> 

So vMX2 will swap the label for 300320 and send it out the interface facing vMX3. vMX3 will…

[email protected]> show route table mpls.0 label 300320 

mpls.0: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

300320             *[VPN/170] 00:05:31, metric2 2, from 4.4.4.4
                    > to 169.254.10.5 via ge-0/0/1.0, Swap 300240

[email protected]> 

Swap the label for 300240 and send it out the interface facing vMX4. So far so good. vMX4 will…

[email protected]> show route table ?            
Possible completions:
  <table>              Name of routing table
  inet.0               
  inet6.0              
[email protected]> show route table

Well….. vMX4 doesn’t even have a mpls.0 table. As we’ve learned before mpls.0 is where we typically look to see what a router might do if it’s acting as a transit MPLS router. The lack of the table existing means that there are no entries. So what does that tell us? Let’s look at the route that vMX4 is sending vMX3…

[email protected]> show route advertising-protocol bgp 3.3.3.3 extensive 192.168.10.0/24 

inet.0: 15 destinations, 15 routes (15 active, 0 holddown, 0 hidden)
* 192.168.10.0/24 (1 entry, 1 announced)
 BGP group internal-1 type Internal
     Route Label: 300240
     Nexthop: 5.5.5.5
     Localpref: 100
     AS path: [65003] 65006 65007 I 
     Cluster ID: 0.0.0.0
     Originator ID: 5.5.5.5
     Entropy label capable

[email protected]> 

Alright – now let’s look at the advertisement vMX4 is receiving from vMX5….

[email protected]> show route receive-protocol bgp 5.5.5.5 extensive 192.168.10.0/24        

inet.0: 15 destinations, 15 routes (15 active, 0 holddown, 0 hidden)
* 192.168.10.0/24 (1 entry, 1 announced)
     Accepted
     Route Label: 300240
     Nexthop: 5.5.5.5
     Localpref: 100
     AS path: 65006 65007 I 
     Entropy label capable, next hop field matches route next hop

[email protected]> 

Looking at this output from a purely BGP perspective this all makes sense to me. You likely noticed that we configured vMX4 to be a router reflector as part of the AS 65003 iBGP configuration. So vMX4 is simply passing along the advertisement it’s receiving from vMX5 to vMX3. But this is where it’s important to understand how label allocation works in regards to BGP. The rule is…

Anytime a router changes the next-hop of a prefix it’s advertising – it must allocate a new label.

Commit the above statement to your long term memory – it’s worth remembering. So how does this apply to our scenario? vMX4 is acting like a route reflector which means it’s not changing the next-hop address of the prefixes it’s sending to vMX3. If you look you’ll see that the next-hop address it’s receiving (as well as the label) is the same as it’s receiving from vMX5. Why is this a problem? Because we no longer have an end to end LSP between vMX1 and vMX7. The traffic is arriving at vMX4 with a label that vMX5 allocated which is why when we look at vMX4 we see that there is not mpls.0 table. vMX4 hasn’t allocated any labels.

By this point – hopefully the idea of locally significant labels has been beaten into your brain. Since the label vMX4 is passing along from vMX5 wasn’t allocated by vMX4 – vMX4 will have no idea what to do with it so it wastes no time at all dropping the frame.

So how do we fix this? Any guesses? The quick fix for this would be to configure out route reflector to change the next-hop address to self. Let’s do that quick and see if that clears things up…

vMX4

set policy-options policy-statement nhs from protocol bgp
set policy-options policy-statement nhs then next-hop self
set protocols bgp group internal-1 export nhs

After committing that – we should see that out ping is now once again working….

[email protected]_client:~# ping 192.168.10.100 -c 5
PING 192.168.10.100 (192.168.10.100) 56(84) bytes of data.
64 bytes from 192.168.10.100: icmp_seq=1 ttl=57 time=4.55 ms
64 bytes from 192.168.10.100: icmp_seq=2 ttl=57 time=5.11 ms
64 bytes from 192.168.10.100: icmp_seq=3 ttl=57 time=4.88 ms
64 bytes from 192.168.10.100: icmp_seq=4 ttl=57 time=5.55 ms
64 bytes from 192.168.10.100: icmp_seq=5 ttl=57 time=3.95 ms

--- 192.168.10.100 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 3.955/4.812/5.553/0.539 ms
[email protected]_client:~# 

Awesome – and if we look at the advertisements from label vMX4 to vMX3 – we should see a label is being allocated that vMX4 has a matching action for in it’s mpls.0 table…

[email protected]> show route advertising-protocol bgp 3.3.3.3 extensive 192.168.10.0/24    

inet.0: 15 destinations, 15 routes (15 active, 0 holddown, 0 hidden)
* 192.168.10.0/24 (1 entry, 1 announced)
 BGP group internal-1 type Internal
     Route Label: 300288
     Nexthop: Self
     Flags: Nexthop Change
     Localpref: 100
     AS path: [65003] 65006 65007 I 
     Cluster ID: 0.0.0.0
     Originator ID: 5.5.5.5
     Entropy label capable

[email protected]> show route table mpls.0 label 300288 

mpls.0: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

300288             *[VPN/170] 00:02:10, metric2 1, from 5.5.5.5
                    > to 169.254.10.7 via ge-0/0/1.0, Swap 300240

[email protected]> 

Nice! So we’ve only really scratched the surface here – but I hope this shows you how you can use BGP-LU for label distribution. In the next post – we’re going to try layering on some MPLS services to this setup and see how that works. Stay tuned!

2 thoughts on “Understanding BGP Labeled Unicast

  1. Nabeel Nasir

    As usual , fantastic post about BGP-LU. Looking forward about the next post on Layering MPLS services on the top of it. I am stay tuned to your posts always

    Reply
  2. Nabeel Nasir

    Next-Hop self is required when there is inline-RR which is the case here. In case RR is not line then there is no need for next-hop self policy I guess.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *