summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/ztpv6/parse_remote_id.go
diff options
context:
space:
mode:
authorChris Gorham <gorhamc90@gmail.com>2018-12-12 07:17:09 -0700
committerPablo Mazzini <pmazzini@gmail.com>2018-12-12 14:17:09 +0000
commit2b569280e441c779406c8b2aaa1283ca5ce0f15b (patch)
tree958baf282cbdbce007a2c566dfdec53cb2246c91 /dhcpv6/ztpv6/parse_remote_id.go
parent94fe644699296ec03ad8eadfed31289b1098c5a0 (diff)
[dhcpv6/ztpv6] Adding Parsing Vendor Opts and Parsing Remote Id Opts lib for ztpv6 (#208)
Diffstat (limited to 'dhcpv6/ztpv6/parse_remote_id.go')
-rw-r--r--dhcpv6/ztpv6/parse_remote_id.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/dhcpv6/ztpv6/parse_remote_id.go b/dhcpv6/ztpv6/parse_remote_id.go
new file mode 100644
index 0000000..5991e96
--- /dev/null
+++ b/dhcpv6/ztpv6/parse_remote_id.go
@@ -0,0 +1,84 @@
+package ztpv6
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+
+ "github.com/insomniacslk/dhcp/dhcpv6"
+)
+
+var (
+ // Arista Port, Vlan Pattern
+ aristaPVPattern = regexp.MustCompile("Ethernet(?P<port>[0-9]+):(?P<vlan>[0-9]+)")
+ // Arista Slot, Mod, Port Pattern
+ aristaSMPPattern = regexp.MustCompile("Ethernet(?P<slot>[0-9]+)/(?P<module>[0-9]+)/(?P<port>[0-9]+)")
+)
+
+// CircuitID represents the structure of network vendor interface formats
+type CircuitID struct {
+ Slot string
+ Module string
+ Port string
+ SubPort string
+ Vlan string
+}
+
+// ParseRemoteId will parse the RemoteId Option data for Vendor Specific data
+func ParseRemoteId(packet dhcpv6.DHCPv6) (*CircuitID, error) {
+ // Need to decapsulate the packet after multiple relays in order to reach RemoteId data
+ inner, err := dhcpv6.DecapsulateRelayIndex(packet, -1)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decapsulate relay index: %v", err)
+ }
+
+ if rid := inner.GetOneOption(dhcpv6.OptionRemoteID); rid != nil {
+ remoteID := string(rid.(*dhcpv6.OptRemoteId).RemoteID())
+ circ, err := matchCircuitId(remoteID)
+ if err != nil {
+ return nil, err
+ }
+ return circ, nil
+ }
+ return nil, errors.New("failed to parse RemoteID option data")
+}
+
+func matchCircuitId(remoteID string) (*CircuitID, error) {
+ var names, matches []string
+
+ switch {
+ case aristaPVPattern.MatchString(remoteID):
+ matches = aristaPVPattern.FindStringSubmatch(remoteID)
+ names = aristaPVPattern.SubexpNames()
+ case aristaSMPPattern.MatchString(remoteID):
+ matches = aristaSMPPattern.FindStringSubmatch(remoteID)
+ names = aristaSMPPattern.SubexpNames()
+ }
+
+ if len(matches) == 0 {
+ return nil, fmt.Errorf("no circuitId regex matches for %v", remoteID)
+ }
+
+ var circuit CircuitID
+ for i, match := range matches {
+ switch names[i] {
+ case "port":
+ circuit.Port = match
+ case "slot":
+ circuit.Slot = match
+ case "module":
+ circuit.Module = match
+ case "subport":
+ circuit.SubPort = match
+ case "vlan":
+ circuit.Vlan = match
+ }
+ }
+
+ return &circuit, nil
+}
+
+// FormatCircuitID is the CircuitID format we send in our Bootfile URL for ZTP devices
+func (c *CircuitID) FormatCircuitID() string {
+ return fmt.Sprintf("%v,%v,%v,%v,%v", c.Slot, c.Module, c.Port, c.SubPort, c.Vlan)
+}