1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
package ztpv6
import (
"testing"
"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/stretchr/testify/require"
)
func TestCircuitID(t *testing.T) {
tt := []struct {
name string
circuit string
want *CircuitID
fail bool
}{
{name: "Bogus string", circuit: "ope/1/2/3:ope", fail: true, want: nil},
{name: "Bogus test", circuit: "bogusInterface", fail: true, want: nil},
{name: "juniperQFX pattern et", circuit: "et-0/0/0:0.0", want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{name: "juniperQFX pattern xe", circuit: "xe-0/0/14:2", want: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}},
{name: "juniperPTX pattern", circuit: "et-0/0/0.0", want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{name: "Juniper QFX pattern", circuit: "et-1/0/61", want: &CircuitID{Slot: "1", Module: "0", Port: "61"}},
{name: "Arista Vlan pattern 1", circuit: "Ethernet14:Vlan2001", want: &CircuitID{Port: "14", Vlan: "Vlan2001"}},
{name: "Arista Vlan pattern 2", circuit: "Ethernet10:2020", want: &CircuitID{Port: "10", Vlan: "2020"}},
{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"}},
{name: "Cisco pattern", circuit: "Gi1/10:2020", want: &CircuitID{Slot: "1", Port: "10", Vlan: "2020"}},
{name: "Cisco Nexus pattern", circuit: "Ethernet1/3", want: &CircuitID{Slot: "1", Port: "3"}},
{name: "Juniper Bundle Pattern", circuit: "ae52.0", want: &CircuitID{Port: "52", SubPort: "0"}},
{name: "Arista Vlan pattern 1 with circuitid type and length", circuit: "\x00\x0fEthernet14:2001", want: &CircuitID{Port: "14", Vlan: "2001"}},
{name: "juniperEX pattern", circuit: "ge-0/0/0.0:RANDOMCHAR", want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
circuit, err := matchCircuitId(tc.circuit)
if err != nil && !tc.fail {
t.Errorf("unexpected failure: %v", err)
}
if circuit != nil {
require.Equal(t, *tc.want, *circuit, "comparing remoteID data")
}
})
}
}
func TestFormatCircuitID(t *testing.T) {
tt := []struct {
name string
circuit *CircuitID
want string
}{
{name: "empty", circuit: &CircuitID{}, want: ",,,,"},
{name: "empty", circuit: &CircuitID{}, want: ",,,,"},
{name: "juniperQFX pattern et", circuit: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}, want: "0,0,0,0,"},
{name: "juniperQFX pattern xe", circuit: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}, want: "0,0,14,2,"},
{name: "juniperPTX pattern", circuit: &CircuitID{Slot: "0", Module: "0", Port: "0"}, want: "0,0,0,,"},
{name: "Arista pattern", circuit: &CircuitID{Slot: "3", Module: "17", Port: "1"}, want: "3,17,1,,"},
{name: "Juniper QFX pattern", circuit: &CircuitID{Slot: "1", Module: "0", Port: "61"}, want: "1,0,61,,"},
{name: "Arista Vlan pattern 1", circuit: &CircuitID{Port: "14", Vlan: "Vlan2001"}, want: ",,14,,Vlan2001"},
{name: "Arista Vlan pattern 2", circuit: &CircuitID{Port: "10", Vlan: "2020"}, want: ",,10,,2020"},
{name: "Cisco Nexus pattern", circuit: &CircuitID{Slot: "1", Port: "3"}, want: "1,,3,,"},
{name: "Juniper Bundle Pattern", circuit: &CircuitID{Port: "52", SubPort: "0"}, want: ",,52,0,"},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
circuit := tc.circuit.FormatCircuitID()
require.Equal(t, tc.want, circuit, "FormatRemoteID data")
})
}
}
func TestParseRemoteID(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: "Bogus test", circuit: []byte("bogusInterface"), fail: true, want: nil},
{name: "juniperQFX pattern et", circuit: []byte("et-0/0/0:0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{name: "juniperQFX pattern xe", circuit: []byte("xe-0/0/14:2"), want: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}},
{name: "juniperPTX pattern", circuit: []byte("et-0/0/0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{name: "Arista pattern", circuit: []byte("Ethernet3/17/1"), want: &CircuitID{Slot: "3", Module: "17", Port: "1"}},
{name: "Juniper QFX pattern", circuit: []byte("et-1/0/61"), want: &CircuitID{Slot: "1", Module: "0", Port: "61"}},
{name: "Arista Vlan pattern 1", circuit: []byte("Ethernet14:Vlan2001"), want: &CircuitID{Port: "14", Vlan: "Vlan2001"}},
{name: "Arista Vlan pattern 2", circuit: []byte("Ethernet10:2020"), want: &CircuitID{Port: "10", Vlan: "2020"}},
{name: "Cisco pattern", circuit: []byte("Gi1/10:2020"), want: &CircuitID{Slot: "1", Port: "10", Vlan: "2020"}},
{name: "Cisco Nexus pattern", circuit: []byte("Ethernet1/3"), want: &CircuitID{Slot: "1", Port: "3"}},
{name: "Juniper Bundle Pattern", circuit: []byte("ae52.0"), want: &CircuitID{Port: "52", SubPort: "0"}},
{name: "Arista Vlan pattern 1 with circuitid type and length", circuit: []byte("\x00\x0fEthernet14:2001"), want: &CircuitID{Port: "14", Vlan: "2001"}},
{name: "juniperEX pattern", circuit: []byte("ge-0/0/0.0:RANDOMCHAR"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
}
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.OptRemoteID{RemoteID: tc.circuit, EnterpriseNumber: 1234})
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")
}
})
}
}
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: "Bogus test", circuit: []byte("bogusInterface"), fail: true, want: nil},
{name: "juniperQFX pattern et", circuit: []byte("et-0/0/0:0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{name: "juniperQFX pattern xe", circuit: []byte("xe-0/0/14:2"), want: &CircuitID{Slot: "0", Module: "0", Port: "14", SubPort: "2"}},
{name: "juniperPTX pattern", circuit: []byte("et-0/0/0.0"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{name: "Arista pattern", circuit: []byte("Ethernet3/17/1"), want: &CircuitID{Slot: "3", Module: "17", Port: "1"}},
{name: "Juniper QFX pattern", circuit: []byte("et-1/0/61"), want: &CircuitID{Slot: "1", Module: "0", Port: "61"}},
{name: "Arista Vlan pattern 1", circuit: []byte("Ethernet14:Vlan2001"), want: &CircuitID{Port: "14", Vlan: "Vlan2001"}},
{name: "Arista Vlan pattern 2", circuit: []byte("Ethernet10:2020"), want: &CircuitID{Port: "10", Vlan: "2020"}},
{name: "Cisco pattern", circuit: []byte("Gi1/10:2020"), want: &CircuitID{Slot: "1", Port: "10", Vlan: "2020"}},
{name: "Cisco Nexus pattern", circuit: []byte("Ethernet1/3"), want: &CircuitID{Slot: "1", Port: "3"}},
{name: "Juniper Bundle Pattern", circuit: []byte("ae52.0"), want: &CircuitID{Port: "52", SubPort: "0"}},
{name: "Arista Vlan pattern 1 with circuitid type and length", circuit: []byte("\x00\x0fEthernet14:2001"), want: &CircuitID{Port: "14", Vlan: "2001"}},
{name: "juniperEX pattern", circuit: []byte("ge-0/0/0.0:RANDOMCHAR"), want: &CircuitID{Slot: "0", Module: "0", Port: "0", SubPort: "0"}},
{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")
}
})
}
}
|