summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp/bgp.go
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-11-15 22:58:57 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-11-21 10:56:23 +0900
commit5713ff22a9ca8d5b587b55f0b7f9c4c49e90c113 (patch)
tree6b3f0335897f5cc1e1ec011670005a551abca1bd /packet/bgp/bgp.go
parentf974b98c6acd8d298c27fb5f7c0c4b2925c5de19 (diff)
packet/bgp: EVPN ESI parser from string slice
This patch introduces a new function to parse EVPN ESI from string slice which passed via CLI for example. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Diffstat (limited to 'packet/bgp/bgp.go')
-rw-r--r--packet/bgp/bgp.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go
index 6e58d5e2..3cd09ecf 100644
--- a/packet/bgp/bgp.go
+++ b/packet/bgp/bgp.go
@@ -1981,6 +1981,138 @@ func (esi *EthernetSegmentIdentifier) String() string {
return s.String()
}
+// Decode Ethernet Segment Identifier (ESI) from string slice.
+//
+// The first element of args should be the Type field (e.g., "ARBITRARY",
+// "arbitrary", "ESI_ARBITRARY" or "esi_arbitrary") and "single-homed" is
+// the special keyword for all zeroed ESI.
+// For the "ARBITRARY" Value field (Type 0), it should be the colon separated
+// hex values and the number of elements should be 9 at most.
+// e.g.) args := []string{"ARBITRARY", "11:22:33:44:55:66:77:88:99"}
+// For the other types, the Value field format is the similar to the string
+// format of ESI.
+// e.g.) args := []string{"lacp", "aa:bb:cc:dd:ee:ff", "100"}
+func ParseEthernetSegmentIdentifier(args []string) (EthernetSegmentIdentifier, error) {
+ esi := EthernetSegmentIdentifier{}
+ argLen := len(args)
+ if argLen == 0 || args[0] == "single-homed" {
+ return esi, nil
+ }
+
+ typeStr := strings.TrimPrefix(strings.ToUpper(args[0]), "ESI_")
+ switch typeStr {
+ case "ARBITRARY":
+ esi.Type = ESI_ARBITRARY
+ case "LACP":
+ esi.Type = ESI_LACP
+ case "MSTP":
+ esi.Type = ESI_MSTP
+ case "MAC":
+ esi.Type = ESI_MAC
+ case "ROUTERID":
+ esi.Type = ESI_ROUTERID
+ case "AS":
+ esi.Type = ESI_AS
+ default:
+ typ, err := strconv.Atoi(args[0])
+ if err != nil {
+ return esi, fmt.Errorf("invalid esi type: %s", args[0])
+ }
+ esi.Type = ESIType(typ)
+ }
+
+ invalidEsiValuesError := fmt.Errorf("invalid esi values for type %s: %s", esi.Type.String(), args[1:])
+ esi.Value = make([]byte, 9, 9)
+ switch esi.Type {
+ case ESI_LACP:
+ fallthrough
+ case ESI_MSTP:
+ if argLen < 3 {
+ return esi, invalidEsiValuesError
+ }
+ // MAC
+ mac, err := net.ParseMAC(args[1])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ copy(esi.Value[0:6], mac)
+ // Port Key or Bridge Priority
+ i, err := strconv.Atoi(args[2])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ binary.BigEndian.PutUint16(esi.Value[6:8], uint16(i))
+ case ESI_MAC:
+ if argLen < 3 {
+ return esi, invalidEsiValuesError
+ }
+ // MAC
+ mac, err := net.ParseMAC(args[1])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ copy(esi.Value[0:6], mac)
+ // Local Discriminator
+ i, err := strconv.Atoi(args[2])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ iBuf := make([]byte, 4, 4)
+ binary.BigEndian.PutUint32(iBuf, uint32(i))
+ copy(esi.Value[6:9], iBuf[1:4])
+ case ESI_ROUTERID:
+ if argLen < 3 {
+ return esi, invalidEsiValuesError
+ }
+ // Router ID
+ ip := net.ParseIP(args[1])
+ if ip == nil || ip.To4() == nil {
+ return esi, invalidEsiValuesError
+ }
+ copy(esi.Value[0:4], ip.To4())
+ // Local Discriminator
+ i, err := strconv.Atoi(args[2])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ binary.BigEndian.PutUint32(esi.Value[4:8], uint32(i))
+ case ESI_AS:
+ if argLen < 3 {
+ return esi, invalidEsiValuesError
+ }
+ // AS
+ as, err := strconv.Atoi(args[1])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ binary.BigEndian.PutUint32(esi.Value[0:4], uint32(as))
+ // Local Discriminator
+ i, err := strconv.Atoi(args[2])
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ binary.BigEndian.PutUint32(esi.Value[4:8], uint32(i))
+ case ESI_ARBITRARY:
+ fallthrough
+ default:
+ if argLen < 2 {
+ // Assumes the Value field is omitted
+ break
+ }
+ values := make([]byte, 0, 9)
+ for _, e := range strings.SplitN(args[1], ":", 9) {
+ v, err := strconv.ParseUint(e, 16, 16)
+ if err != nil {
+ return esi, invalidEsiValuesError
+ }
+ values = append(values, byte(v))
+ }
+ copy(esi.Value, values)
+ }
+
+ return esi, nil
+}
+
//
// I-D bess-evpn-overlay-01
//