diff options
author | IWASE Yusuke <iwase.yusuke0@gmail.com> | 2018-02-08 14:45:12 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2018-02-16 11:28:02 +0900 |
commit | 421a3840e00b4508567c040b5241b3e74cf711e8 (patch) | |
tree | 8376d27ad9b64da857718672436f82dfe11776b6 | |
parent | 9fbec19c4c2624df842ab33bb91943bd9befdffa (diff) |
cli: Support to advertise PMSI Tunnel Attribute
This patch enables "gobgp" command to advertise the PMSI Tunnel
Attribute which is appended to the EVPN Inclusive Multicast Ethernet Tag
routes for example.
Usage Example:
$ gobgp global rib -a evpn add multicast 10.0.0.1 etag 10 rd 65000:100 pmsi ingress-repl 100 1.1.1.1
$ gobgp global rib -a evpn
Network Labels Next Hop AS_PATH Age Attrs
*> [type:multicast][rd:65000:100][etag:10][ip:10.0.0.1] 0.0.0.0 00:00:00 [{Origin: ?} {Pmsi: type: ingress-repl, label: 100, tunnel-id: 1.1.1.1}]
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
-rw-r--r-- | docs/sources/evpn.md | 7 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 35 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 47 |
3 files changed, 76 insertions, 13 deletions
diff --git a/docs/sources/evpn.md b/docs/sources/evpn.md index 176dca3c..ddf80376 100644 --- a/docs/sources/evpn.md +++ b/docs/sources/evpn.md @@ -149,7 +149,7 @@ $ gobgp global rib -a evpn del macadv aa:bb:cc:dd:ee:ff 10.0.0.1 esi AS 65000 10 ```bash # Add a route -$ gobgp global rib -a evpn add multicast <ip address> etag <etag> rd <rd> [rt <rt>...] [encap <encap type>] +$ gobgp global rib -a evpn add multicast <ip address> etag <etag> rd <rd> [rt <rt>...] [encap <encap type>] [pmsi <type> [leaf-info-required] <label> <tunnel-id>] # Show routes $ gobgp global rib -a evpn [multicast] @@ -169,11 +169,10 @@ $ gobgp global rib -a evpn $ gobgp global rib -a evpn del multicast 10.0.0.1 etag 100 rd 1.1.1.1:65000 # With optionals -$ gobgp global rib -a evpn add multicast 10.0.0.1 etag 100 rd 1.1.1.1:65000 rt 65000:200 encap vxlan +$ gobgp global rib -a evpn add multicast 10.0.0.1 etag 100 rd 1.1.1.1:65000 rt 65000:200 encap vxlan pmsi ingress-repl 100 1.1.1.1 $ gobgp global rib -a evpn multicast Network Labels Next Hop AS_PATH Age Attrs -*> [type:multicast][rd:1.1.1.1:65000][etag:100][ip:10.0.0.1] 0.0.0.0 00:00:00 [{Origin: ?} {Extcomms: [65000:200], [VXLAN]}] -$ gobgp global rib -a evpn del multicast 10.0.0.1 etag 100 rd 1.1.1.1:65000 +*> [type:multicast][rd:1.1.1.1:65000][etag:100][ip:10.0.0.1] 0.0.0.0 00:00:00 [{Origin: ?} {Pmsi: type: ingress-repl, label: 100, tunnel-id: 1.1.1.1} {Extcomms: [65000:200], [VXLAN]}] ``` ### Ethernet Segment Route diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go index 2c7a71d6..81506802 100644 --- a/gobgp/cmd/global.go +++ b/gobgp/cmd/global.go @@ -961,6 +961,22 @@ func extractLargeCommunity(args []string) ([]string, bgp.PathAttributeInterface, return args, nil, nil } +func extractPmsiTunnel(args []string) ([]string, bgp.PathAttributeInterface, error) { + for idx, arg := range args { + if arg == "pmsi" { + pmsi, err := bgp.ParsePmsiTunnel(args[idx+1:]) + if err != nil { + return nil, nil, err + } + if pmsi.IsLeafInfoRequired { + return append(args[:idx], args[idx+5:]...), pmsi, nil + } + return append(args[:idx], args[idx+4:]...), pmsi, nil + } + } + return args, nil, nil +} + func extractAigp(args []string) ([]string, bgp.PathAttributeInterface, error) { for idx, arg := range args { if arg == "aigp" { @@ -1028,14 +1044,15 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) { attrs := table.PathAttrs(make([]bgp.PathAttributeInterface, 0, 1)) fns := []func([]string) ([]string, bgp.PathAttributeInterface, error){ - extractAsPath, - extractOrigin, - extractMed, - extractLocalPref, - extractCommunity, - extractAigp, - extractAggregator, - extractLargeCommunity, + extractOrigin, // 1 ORIGIN + extractAsPath, // 2 AS_PATH + extractMed, // 4 MULTI_EXIT_DISC + extractLocalPref, // 5 LOCAL_PREF + extractAggregator, // 7 AGGREGATOR + extractCommunity, // 8 COMMUNITY + extractPmsiTunnel, // 22 PMSI_TUNNEL + extractAigp, // 26 AIGP + extractLargeCommunity, // 32 LARGE_COMMUNITY } for _, fn := range fns { @@ -1351,7 +1368,7 @@ usage: %s rib -a %%s %s%%s match <MATCH> then <THEN>%%s%%s%%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] - <MULTICAST> : <ip address> etag <etag> rd <rd> [rt <rt>...] [encap <encap type>] + <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>]`, err, diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index df2e1571..8e9288e0 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -7927,6 +7927,53 @@ func NewPathAttributePmsiTunnel(typ PmsiTunnelType, isLeafInfoRequired bool, lab } } +func ParsePmsiTunnel(args []string) (*PathAttributePmsiTunnel, error) { + // Format: + // "<type>" ["leaf-info-required"] "<label>" "<tunnel-id>" + if len(args) < 3 { + return nil, fmt.Errorf("invalid pmsi tunnel arguments: %s", args) + } + + pmsi := NewPathAttributePmsiTunnel(0, false, 0, nil) + + switch args[0] { + case "ingress-repl": + pmsi.TunnelType = PMSI_TUNNEL_TYPE_INGRESS_REPL + default: + typ, err := strconv.ParseUint(args[0], 10, 8) + if err != nil { + return nil, fmt.Errorf("invalid pmsi tunnel type: %s", args[0]) + } + pmsi.TunnelType = PmsiTunnelType(typ) + } + + indx := 1 + if args[indx] == "leaf-info-required" { + pmsi.IsLeafInfoRequired = true + indx++ + } + + label, err := strconv.ParseUint(args[indx], 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid pmsi tunnel label: %s", args[indx]) + } + pmsi.Label = uint32(label) + indx++ + + switch pmsi.TunnelType { + case PMSI_TUNNEL_TYPE_INGRESS_REPL: + ip := net.ParseIP(args[indx]) + if ip == nil { + return nil, fmt.Errorf("invalid pmsi tunnel identifier: %s", args[indx]) + } + pmsi.TunnelID = &IngressReplTunnelID{Value: ip} + default: + pmsi.TunnelID = &DefaultPmsiTunnelID{Value: []byte(args[indx])} + } + + return pmsi, nil +} + type AigpTLVType uint8 const ( |