From 5dd7202f19711228cb4a51aa8b3415421c2edefe Mon Sep 17 00:00:00 2001 From: akshay navale Date: Wed, 1 Apr 2020 11:58:30 -0600 Subject: adding fallback logic to remote id parsing Signed-off-by: akshay navale --- dhcpv6/ztpv6/parse_remote_id.go | 27 +++++++++++++++++---------- dhcpv6/ztpv6/parse_remote_id_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/dhcpv6/ztpv6/parse_remote_id.go b/dhcpv6/ztpv6/parse_remote_id.go index 9de9bdf..9dd72b1 100644 --- a/dhcpv6/ztpv6/parse_remote_id.go +++ b/dhcpv6/ztpv6/parse_remote_id.go @@ -36,29 +36,36 @@ func ParseRemoteID(packet dhcpv6.DHCPv6) (*CircuitID, error) { if rid := rm.Options.RemoteID(); rid != nil { remoteID := string(rid.RemoteID) circ, err := matchCircuitId(remoteID) - if err != nil { - return nil, err + if err == nil { + return circ, nil + } + } + // if we fail to find circuit id from remote id try to use interface ID option + if iid := rm.Options.InterfaceID(); iid != nil { + interfaceID := string(iid) + circ, err := matchCircuitId(interfaceID) + if err == nil { + return circ, nil } - return circ, nil } } - return nil, errors.New("failed to parse RemoteID option data") + return nil, errors.New("failed to parse RemoteID and InterfaceID option data") } -func matchCircuitId(remoteID string) (*CircuitID, error) { +func matchCircuitId(circuitInfo string) (*CircuitID, error) { var names, matches []string switch { - case aristaPVPattern.MatchString(remoteID): - matches = aristaPVPattern.FindStringSubmatch(remoteID) + case aristaPVPattern.MatchString(circuitInfo): + matches = aristaPVPattern.FindStringSubmatch(circuitInfo) names = aristaPVPattern.SubexpNames() - case aristaSMPPattern.MatchString(remoteID): - matches = aristaSMPPattern.FindStringSubmatch(remoteID) + case aristaSMPPattern.MatchString(circuitInfo): + matches = aristaSMPPattern.FindStringSubmatch(circuitInfo) names = aristaSMPPattern.SubexpNames() } if len(matches) == 0 { - return nil, fmt.Errorf("no circuitId regex matches for %v", remoteID) + return nil, fmt.Errorf("no circuitId regex matches for %v", circuitInfo) } var circuit CircuitID diff --git a/dhcpv6/ztpv6/parse_remote_id_test.go b/dhcpv6/ztpv6/parse_remote_id_test.go index 48d20bc..6147cec 100644 --- a/dhcpv6/ztpv6/parse_remote_id_test.go +++ b/dhcpv6/ztpv6/parse_remote_id_test.go @@ -17,6 +17,7 @@ func TestCircuitID(t *testing.T) { {name: "Bogus string", circuit: "ope/1/2/3:ope", fail: true, want: nil}, {name: "Arista Port Vlan Pattern", circuit: "Ethernet13:2001", want: &CircuitID{Port: "13", Vlan: "2001"}}, {name: "Arista Slot Module Port Pattern", circuit: "Ethernet1/3/4", want: &CircuitID{Slot: "1", Module: "3", Port: "4"}}, + {name: "Arista Slot Module Port Pattern InterfaceID", circuit: "Ethernet1/3/4:default", want: &CircuitID{Slot: "1", Module: "3", Port: "4"}}, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { @@ -83,3 +84,34 @@ func TestParseRemoteID(t *testing.T) { }) } } + +func TestParseRemoteIDWithInterfaceID(t *testing.T) { + tt := []struct { + name string + circuit []byte + want *CircuitID + fail bool + }{ + {name: "Bogus string", circuit: []byte("ope/1/2/3:ope.1"), fail: true, want: nil}, + {name: "Arista Slot Module Port Pattern", circuit: []byte("Ethernet1/3/4:default"), want: &CircuitID{Slot: "1", Module: "3", Port: "4"}}, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + m := &dhcpv6.RelayMessage{ + MessageType: dhcpv6.MessageTypeRelayForward, + } + // Has to be a well-formed relay message with the OptRelayMsg. + m.Options.Add(dhcpv6.OptRelayMessage(&dhcpv6.Message{})) + m.Options.Add(dhcpv6.OptInterfaceID(tc.circuit)) + circuit, err := ParseRemoteID(m) + if err != nil && !tc.fail { + t.Errorf("unexpected failure: %v", err) + } + if circuit != nil { + require.Equal(t, *tc.want, *circuit, "ZTPRemoteID data") + } else { + require.Equal(t, tc.want, circuit, "ZTPRemoteID data") + } + }) + } +} -- cgit v1.2.3