diff options
author | Emanuele Fia <name29@fb.com> | 2022-03-31 20:38:34 +0100 |
---|---|---|
committer | Emanuele Fia <name29@fb.com> | 2022-04-01 16:51:08 +0100 |
commit | cef7f4a9829be517745c0c07658f1344989d150f (patch) | |
tree | 8da20e3c66df0b3243effa07291f204eef15027f | |
parent | 07cc76ec259f5fff3e81e11b340167a690bca9a1 (diff) |
Adding support for DHCPv6 for Ciena
Signed-off-by: Emanuele Fia <name29@fb.com>
-rw-r--r-- | dhcpv6/dhcpv6.go | 4 | ||||
-rw-r--r-- | dhcpv6/dhcpv6_test.go | 25 | ||||
-rw-r--r-- | dhcpv6/option_userclass.go | 6 | ||||
-rw-r--r-- | dhcpv6/option_userclass_test.go | 10 | ||||
-rw-r--r-- | dhcpv6/options.go | 6 | ||||
-rw-r--r-- | dhcpv6/ztpv6/parse_remote_id.go | 78 | ||||
-rw-r--r-- | dhcpv6/ztpv6/parse_remote_id_test.go | 53 | ||||
-rw-r--r-- | dhcpv6/ztpv6/parse_vendor_options.go | 8 | ||||
-rw-r--r-- | dhcpv6/ztpv6/parse_vendor_options_test.go | 69 |
9 files changed, 63 insertions, 196 deletions
diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go index 31e6abf..59d9733 100644 --- a/dhcpv6/dhcpv6.go +++ b/dhcpv6/dhcpv6.go @@ -75,7 +75,7 @@ func RelayMessageFromBytes(data []byte) (*RelayMessage, error) { } // TODO: fail if no OptRelayMessage is present. if err := d.Options.FromBytes(buf.Data()); err != nil { - return nil, fmt.Errorf("Unable to parse Options: %v", err) + return nil, err } return d, nil } @@ -85,7 +85,7 @@ func FromBytes(data []byte) (DHCPv6, error) { buf := uio.NewBigEndianBuffer(data) messageType := MessageType(buf.Read8()) if buf.Error() != nil { - return nil, fmt.Errorf("Unable to parse MessageType: %v", buf.Error()) + return nil, buf.Error() } if messageType == MessageTypeRelayForward || messageType == MessageTypeRelayReply { diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go index cd235f1..b1f952d 100644 --- a/dhcpv6/dhcpv6_test.go +++ b/dhcpv6/dhcpv6_test.go @@ -133,31 +133,6 @@ func TestFromAndToBytes(t *testing.T) { expected := [][]byte{ {01, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00}, []byte("0000\x00\x01\x00\x0e\x00\x01000000000000"), - { - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x09, 0x00, 0x72, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x44, 0x48, - 0x00, 0x06, 0x00, 0x0a, 0x00, 0x3b, 0x00, 0x17, - 0x00, 0x02, 0x00, 0x0c, 0x00, 0x38, 0x00, 0x08, - 0x00, 0x02, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x15, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2e, 0x30, 0x30, 0x35, 0x32, 0x00, 0x10, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x0c, 0x1a, 0x8e, 0xee, 0x04, - 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x15, 0x18, - 0x00, 0x35, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00}, } t.Parallel() for i, packet := range expected { diff --git a/dhcpv6/option_userclass.go b/dhcpv6/option_userclass.go index 2900d2a..e5d7b31 100644 --- a/dhcpv6/option_userclass.go +++ b/dhcpv6/option_userclass.go @@ -50,9 +50,5 @@ func ParseOptUserClass(data []byte) (*OptUserClass, error) { len := buf.Read16() opt.UserClasses = append(opt.UserClasses, buf.CopyN(int(len))) } - var err = buf.FinError() - if err != nil { - err = fmt.Errorf("Unable to parse OptUserClass: %v", err) - } - return &opt, err + return &opt, buf.FinError() } diff --git a/dhcpv6/option_userclass_test.go b/dhcpv6/option_userclass_test.go index 562ee74..16fae72 100644 --- a/dhcpv6/option_userclass_test.go +++ b/dhcpv6/option_userclass_test.go @@ -91,13 +91,3 @@ func TestOptUserClassString(t *testing.T) { "String() should contain the list of user classes", ) } - -func TestOptUserClassParseOptUserClassCiena(t *testing.T) { - buf := []byte{ - 0x00, 0x13, 0x31, 0x2f, 0x52, - 0x4c, 0x53, 0x2d, 0x30, 0x32, 0x2e, 0x30, 0x34, - 0x2e, 0x30, 0x32, 0x2e, 0x30, 0x30, 0x35, 0x32, - } - _, err := ParseOptUserClass(buf) - require.NoError(t, err) -} diff --git a/dhcpv6/options.go b/dhcpv6/options.go index bf523dd..f8445bb 100644 --- a/dhcpv6/options.go +++ b/dhcpv6/options.go @@ -208,12 +208,10 @@ func (o *Options) FromBytesWithParser(data []byte, parser OptionParser) error { // Consume, but do not Copy. Each parser will make a copy of // pertinent data. optData := buf.Consume(length) - if err := buf.Error(); err != nil { - return fmt.Errorf("Unable to read payload of option code %d with option length %d: %v", code, length, err) - } + opt, err := parser(code, optData) if err != nil { - return fmt.Errorf("Unable to parse option code %d with option length %d : %v [data %x]", code, length, err, optData) + return err } *o = append(*o, opt) } diff --git a/dhcpv6/ztpv6/parse_remote_id.go b/dhcpv6/ztpv6/parse_remote_id.go index 8b1488a..9dd72b1 100644 --- a/dhcpv6/ztpv6/parse_remote_id.go +++ b/dhcpv6/ztpv6/parse_remote_id.go @@ -8,32 +8,12 @@ import ( "github.com/insomniacslk/dhcp/dhcpv6" ) -var circuitRegexs = []*regexp.Regexp{ +var ( // Arista Port, Vlan Pattern - regexp.MustCompile("Ethernet(?P<port>[0-9]+):(?P<vlan>[0-9]+)"), + aristaPVPattern = regexp.MustCompile("Ethernet(?P<port>[0-9]+):(?P<vlan>[0-9]+)") // Arista Slot, Mod, Port Pattern - regexp.MustCompile("Ethernet(?P<slot>[0-9]+)/(?P<mod>[0-9]+)/(?P<port>[0-9]+)"), - // Juniper QFX et-0/0/0:0.0 and xe-0/0/0:0.0 - regexp.MustCompile("^(et|xe)-(?P<slot>[0-9]+)/(?P<mod>[0-9]+)/(?P<port>[0-9]+):(?P<subport>[0-9]+).*$"), - // Juniper PTX et-0/0/0.0 - regexp.MustCompile("^et-(?P<slot>[0-9]+)/(?P<mod>[0-9]+)/(?P<port>[0-9]+).(?P<subport>[0-9]+)$"), - // Juniper EX ge-0/0/0.0 - regexp.MustCompile("^ge-(?P<slot>[0-9]+)/(?P<mod>[0-9]+)/(?P<port>[0-9]+).(?P<subport>[0-9]+).*"), - // Arista Ethernet3/17/1 - // Sometimes Arista prepend circuit id type(1 byte) and length(1 byte) not using ^ - regexp.MustCompile("Ethernet(?P<slot>[0-9]+)/(?P<mod>[0-9]+)/(?P<port>[0-9]+)$"), - // Juniper QFX et-1/0/61 - regexp.MustCompile("^et-(?P<slot>[0-9]+)/(?P<mod>[0-9]+)/(?P<port>[0-9]+)$"), - // Arista Ethernet14:Vlan2001 - // Arista Ethernet10:2020 - regexp.MustCompile("Ethernet(?P<port>[0-9]+):(?P<vlan>.*)$"), - // Cisco Gi1/10:2020 - regexp.MustCompile("^Gi(?P<slot>[0-9]+)/(?P<port>[0-9]+):(?P<vlan>.*)$"), - // Nexus Ethernet1/3 - regexp.MustCompile("^Ethernet(?P<slot>[0-9]+)/(?P<port>[0-9]+)$"), - // Juniper bundle interface ae52.0 - regexp.MustCompile("^ae(?P<port>[0-9]+).(?P<subport>[0-9])$"), -} + 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 { @@ -73,32 +53,38 @@ func ParseRemoteID(packet dhcpv6.DHCPv6) (*CircuitID, error) { } func matchCircuitId(circuitInfo string) (*CircuitID, error) { - for _, re := range circuitRegexs { + var names, matches []string - match := re.FindStringSubmatch(circuitInfo) - if len(match) == 0 { - continue - } + switch { + case aristaPVPattern.MatchString(circuitInfo): + matches = aristaPVPattern.FindStringSubmatch(circuitInfo) + names = aristaPVPattern.SubexpNames() + case aristaSMPPattern.MatchString(circuitInfo): + matches = aristaSMPPattern.FindStringSubmatch(circuitInfo) + names = aristaSMPPattern.SubexpNames() + } - c := CircuitID{} - for i, k := range re.SubexpNames() { - switch k { - case "slot": - c.Slot = match[i] - case "mod": - c.Module = match[i] - case "port": - c.Port = match[i] - case "subport": - c.SubPort = match[i] - case "vlan": - c.Vlan = match[i] - } - } + if len(matches) == 0 { + return nil, fmt.Errorf("no circuitId regex matches for %v", circuitInfo) + } - return &c, nil + 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 nil, fmt.Errorf("Unable to match circuit id : %s with listed regexes of interface types", circuitInfo) + + return &circuit, nil } // FormatCircuitID is the CircuitID format we send in our Bootfile URL for ZTP devices diff --git a/dhcpv6/ztpv6/parse_remote_id_test.go b/dhcpv6/ztpv6/parse_remote_id_test.go index 8d17c80..6147cec 100644 --- a/dhcpv6/ztpv6/parse_remote_id_test.go +++ b/dhcpv6/ztpv6/parse_remote_id_test.go @@ -15,20 +15,9 @@ func TestCircuitID(t *testing.T) { 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 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"}}, - {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) { @@ -50,16 +39,8 @@ func TestFormatCircuitID(t *testing.T) { 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,"}, + {name: "Arista format Port/Vlan", circuit: &CircuitID{Port: "13", Vlan: "2001"}, want: ",,13,,2001"}, + {name: "Arista format Slot/Module/Port", circuit: &CircuitID{Slot: "1", Module: "3", Port: "4"}, want: "1,3,4,,"}, } for _, tc := range tt { @@ -79,19 +60,8 @@ func TestParseRemoteID(t *testing.T) { 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 Port Vlan Pattern", circuit: []byte("Ethernet13:2001"), want: &CircuitID{Port: "13", Vlan: "2001"}}, + {name: "Arista Slot Module Port Pattern", circuit: []byte("Ethernet1/3/4"), want: &CircuitID{Slot: "1", Module: "3", Port: "4"}}, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { @@ -123,19 +93,6 @@ func TestParseRemoteIDWithInterfaceID(t *testing.T) { 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 { diff --git a/dhcpv6/ztpv6/parse_vendor_options.go b/dhcpv6/ztpv6/parse_vendor_options.go index 3aef837..13983f4 100644 --- a/dhcpv6/ztpv6/parse_vendor_options.go +++ b/dhcpv6/ztpv6/parse_vendor_options.go @@ -81,11 +81,11 @@ func ParseVendorData(packet dhcpv6.DHCPv6) (*VendorData, error) { if len(v) < 3 { return nil, errVendorOptionMalformed } - duid := packet.(*dhcpv6.Message).Options.ClientID() - if duid.Type != dhcpv6.DUID_EN { - return nil, errors.New(fmt.Sprintf("Unexpected DUID type %d for Ciena", duid.Type)) + innerMessage, err := packet.GetInnerMessage() + if err != nil { + return nil, fmt.Errorf("Unable to get inner message: %v", err) } - + duid := innerMessage.Options.ClientID() vd.VendorName = iana.EnterpriseIDCienaCorporation.String() vd.Model = v[1] + "-" + v[2] vd.Serial = string(duid.EnterpriseIdentifier) diff --git a/dhcpv6/ztpv6/parse_vendor_options_test.go b/dhcpv6/ztpv6/parse_vendor_options_test.go index ac5fc81..cd2fb3d 100644 --- a/dhcpv6/ztpv6/parse_vendor_options_test.go +++ b/dhcpv6/ztpv6/parse_vendor_options_test.go @@ -57,10 +57,11 @@ func TestParseVendorDataWithVendorOpts(t *testing.T) { func TestParseVendorDataWithVendorClass(t *testing.T) { tt := []struct { - name string - vc string - want *VendorData - fail bool + name string + vc string + clientId *dhcpv6.Duid + want *VendorData + fail bool }{ {name: "empty", fail: true}, {name: "unknownVendor", vc: "VendorX;BFR10K;XX12345", fail: true, want: nil}, @@ -75,45 +76,14 @@ func TestParseVendorDataWithVendorClass(t *testing.T) { vc: "ZPESystems:NSC:001234567", want: &VendorData{VendorName: "ZPESystems", Model: "NSC", Serial: "001234567"}, }, - } - - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - packet, err := dhcpv6.NewMessage() - if err != nil { - t.Fatalf("failed to creat dhcpv6 packet object: %v", err) - } - - packet.AddOption(&dhcpv6.OptVendorClass{ - EnterpriseNumber: 0000, Data: [][]byte{[]byte(tc.vc)}}) - - vd, err := ParseVendorData(packet) - if err != nil && !tc.fail { - t.Errorf("unexpected failure: %v", err) - } - - if vd != nil { - require.Equal(t, *tc.want, *vd, "comparing vendor class data") - } else { - require.Equal(t, tc.want, vd, "comparing vendor class data") - } - }) - } -} - -func TestParseVendorDataWithClientId(t *testing.T) { - tt := []struct { - name string - vc string - serial string - want *VendorData - fail bool - }{ { - name: "Ciena", - vc: "1271-23422Z11-123", - serial: "001234567", - want: &VendorData{VendorName: iana.EnterpriseIDCienaCorporation.String(), Model: "23422Z11-123", Serial: "001234567"}, + name: "Ciena", + vc: "1271-23422Z11-123", + clientId: &dhcpv6.Duid{ + Type: dhcpv6.DUID_EN, + EnterpriseIdentifier: []byte("001234567"), + }, + want: &VendorData{VendorName: iana.EnterpriseIDCienaCorporation.String(), Model: "23422Z11-123", Serial: "001234567"}, }, } @@ -126,23 +96,18 @@ func TestParseVendorDataWithClientId(t *testing.T) { packet.AddOption(&dhcpv6.OptVendorClass{ EnterpriseNumber: 0000, Data: [][]byte{[]byte(tc.vc)}}) - packet.AddOption(dhcpv6.OptClientID( - dhcpv6.Duid{ - Type: dhcpv6.DUID_EN, - EnterpriseIdentifier: []byte(tc.serial), - }, - ), - ) - + if tc.clientId != nil { + packet.AddOption(dhcpv6.OptClientID(*tc.clientId)) + } vd, err := ParseVendorData(packet) if err != nil && !tc.fail { t.Errorf("unexpected failure: %v", err) } if vd != nil { - require.Equal(t, *tc.want, *vd, "comparing vendor option data") + require.Equal(t, *tc.want, *vd, "comparing vendor class data") } else { - require.Equal(t, tc.want, vd, "comparing vendor option data") + require.Equal(t, tc.want, vd, "comparing vendor class data") } }) } |