summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/sources/evpn.md7
-rw-r--r--gobgp/cmd/global.go35
-rw-r--r--packet/bgp/bgp.go47
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 (