diff options
-rw-r--r-- | docs/sources/evpn.md | 71 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 30 |
2 files changed, 91 insertions, 10 deletions
diff --git a/docs/sources/evpn.md b/docs/sources/evpn.md index ab53fea1..db139231 100644 --- a/docs/sources/evpn.md +++ b/docs/sources/evpn.md @@ -12,6 +12,8 @@ still very experimental. - [Inclusive Multicast Ethernet Tag Route](#inclusive-multicast-ethernet-tag-route) - [Ethernet Segment Route](#ethernet-segment-route) - [IP Prefix Route](#ip-prefix-route) +- [Reference](#reference) + - [Router's MAC Option](#routers-mac-option) - [BaGPipe](#bagpipe) - [Configuration](#configuration) - [Advertising EVPN route](#advertising-evpn-route) @@ -237,6 +239,75 @@ $ gobgp global rib -a evpn prefix $ gobgp global rib -a evpn del prefix 10.0.0.0/24 172.16.0.1 esi MSTP aa:aa:aa:aa:aa:aa 100 etag 200 label 300 rd 1.1.1.1:65000 ``` +## Reference + +### Router's MAC Option + +The `router-mac` option in `gobgp` CLI allows sending Router's +MAC Extended Community via BGP EVPN Type 2 and Type 5 advertisements. + +As explained in below RFC draft, this community is used to carry the +MAC address of the VTEP where MAC-IP pair resides. + +For example, GoBGP router (R1) peers with Cisco router (R2). +R1 is used by an orchestraction platform, e.g. OpenStack, Docker Swarm, +etc., to advertise container MAC-IP bindings. When R1 advertises the +binding it also sets next hop for the route as the host where the MAC-IP +binding (i.e. container) resides. When R2 receives the route, it will +not install it unless Router's MAC Extended Community is present. R2 +will use the MAC address in the community to create an entry in MAC +address table of R2 pointint to NVE interface. + +```bash +gobgp global rib -a evpn add macadv e9:72:d7:aa:1f:b4 \ + 172.16.100.100 etag 0 label 34567 rd 10.1.1.1:100 \ + rt 65001:100 encap vxlan nexthop 10.10.10.10 \ + origin igp router-mac e9:72:d7:aa:1f:b4 + +gobgp global rib -a evpn add nexthop 10.10.10.10 origin igp \ + prefix 172.16.100.100/32 esi 0 etag 0 rd 10.1.1.1:100 \ + rt 65001:100 gw 10.10.10.10 label 34567 encap vxlan \ + router-mac e9:72:d7:aa:1f:b4 +``` + +In the above example, a host with IP of `10.10.10.10` runs a +container connected to an Open vSwitch instance. The container's IP +address is `172.16.100.100` and MAC address `e9:72:d7:aa:1f:b4`. +The Open vSwitch is VTEP with `tunnel_key=34567`, i.e. VNID `34567`. + +GoBGP (R1) and Cisco (R2) routers are in BGP AS 65001. R1's IP is +`10.1.1.1`. R2 used RT of `65001:100` to import routes and place +them into appropriate VRF. In this case the VRF is associated with +L2VNI from VLAN 300. Upon the receipt of the above BGP EVPN +Type 2 and Type 5 routes, R2 will create create a MAC address +entry pointing to it's NVE interface with destination IP address +of `10.10.10.10`. + +```bash +Legend: + * - primary entry, G - Gateway MAC, (R) - Routed MAC, O - Overlay MAC + age - seconds since last seen,+ - primary entry using vPC Peer-Link, + (T) - True, (F) - False, C - ControlPlane MAC + VLAN MAC Address Type age Secure NTFY Ports +---------+-----------------+--------+---------+------+----+------------------ +* 300 e972.d7aa.1fb4 static - F F nve1(10.10.10.10) +``` + +The R2 will use the `router-mac e9:72:d7:aa:1f:b4` as the destination MAC +address of the inner VXLAN packet. For example, an underlay host `20.20.20.20` +ping the container. The inner VXLAN L2 destination address is +`e9:72:d7:aa:1f:b4`. The inner VXLAN L2 source address is R2's MAC. The outer +VXLAN L3 source address, i.e. `10.2.2.2` is R2' NVE address. + +```bash +OUTER VXLAN L2: 10:20:08:d0:ff:23 > b2:0e:19:6a:8d:51 +OUTER VXLAN L3: 10.2.2.2.45532 > 10.10.10.10.4789: VXLAN, flags [I] (0x08), vni 34567 +INNER VXLAN L2: 4e:f4:ca:aa:f6:7b > e9:72:d7:aa:1f:b4 +INNER VXLAN L3: 20.20.20.20 > 172.16.100.100: ICMP echo reply, id 66, seq 1267, length 64 +``` + +See also: [Integrated Routing and Bridging in EVPN](https://tools.ietf.org/html/draft-ietf-bess-evpn-inter-subnet-forwarding-03#section-6.1) + ## BaGPipe This example uses [BaGPipe](https://github.com/openstack/networking-bagpipe). GoBGP receives diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go index c9be51bc..b5851929 100644 --- a/gobgp/cmd/global.go +++ b/gobgp/cmd/global.go @@ -465,22 +465,23 @@ func ParseEvpnEthernetAutoDiscoveryArgs(args []string) (bgp.AddrPrefixInterface, func ParseEvpnMacAdvArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { // Format: - // <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway] + // <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway] // or - // <mac address> <ip address> <etag> [esi <esi>] label <label> rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway] + // <mac address> <ip address> <etag> [esi <esi>] label <label> rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway] // or - // <mac address> <ip address> <etag> <label> [esi <esi>] rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway] + // <mac address> <ip address> <etag> <label> [esi <esi>] rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway] req := 6 if len(args) < req { return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args)) } m, err := extractReserved(args, map[string]int{ - "esi": PARAM_LIST, - "etag": PARAM_SINGLE, - "label": PARAM_SINGLE, - "rd": PARAM_SINGLE, - "rt": PARAM_LIST, - "encap": PARAM_SINGLE}) + "esi": PARAM_LIST, + "etag": PARAM_SINGLE, + "label": PARAM_SINGLE, + "rd": PARAM_SINGLE, + "rt": PARAM_LIST, + "encap": PARAM_SINGLE, + "router-mac": PARAM_SINGLE}) if err != nil { return nil, nil, err } @@ -560,6 +561,15 @@ func ParseEvpnMacAdvArgs(args []string) (bgp.AddrPrefixInterface, []string, erro if len(m["encap"]) > 0 { extcomms = append(extcomms, "encap", m["encap"][0]) } + + if len(m["router-mac"]) != 0 { + _, err := net.ParseMAC(m["router-mac"][0]) + if err != nil { + return nil, nil, fmt.Errorf("invalid router-mac address: %s", m["router-mac"][0]) + } + extcomms = append(extcomms, "router-mac", m["router-mac"][0]) + } + for _, a := range args { if a == "default-gateway" { extcomms = append(extcomms, "default-gateway") @@ -1422,7 +1432,7 @@ usage: %s rib -a %%s %s%%s match <MATCH> then <THEN>%%s%%s%%s helpErrMap[bgp.RF_EVPN] = fmt.Errorf(`error: %s usage: %s rib %s { a-d <A-D> | macadv <MACADV> | multicast <MULTICAST> | esi <ESI> | prefix <PREFIX> } -a evpn <A-D> : esi <esi> etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [esi-label <esi-label> [single-active | all-active]] - <MACADV> : <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [default-gateway] + <MACADV> : <mac address> <ip address> [esi <esi>] etag <etag> label <label> rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>] [default-gateway] <MULTICAST> : <ip address> etag <etag> rd <rd> [rt <rt>...] [encap <encap type>] [pmsi <type> [leaf-info-required] <label> <tunnel-id>] <ESI> : <ip address> esi <esi> rd <rd> [rt <rt>...] [encap <encap type>] <PREFIX> : <ip prefix> [gw <gateway>] [esi <esi>] etag <etag> [label <label>] rd <rd> [rt <rt>...] [encap <encap type>] [router-mac <mac address>]`, |