summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPablo Mazzini <pmazzini@gmail.com>2022-04-05 06:01:11 +0100
committerGitHub <noreply@github.com>2022-04-05 06:01:11 +0100
commit12fbdcb11b41fa90662c34620e09dc7714d67ab3 (patch)
tree0a6a0bd1f513be7e71a363f2ad4c05a90db879ed
parent3c283ff8b7dd3a8ea2dbc37d13a35bba7aab00e5 (diff)
parent9e4611cb531e6234489ccf22973cd6b4d698885d (diff)
Merge pull request #463 from name29/ciena_dhcpv6
Extending parse_circuit_id and adding support for Ciena
-rw-r--r--dhcpv6/ztpv6/README.md1
-rw-r--r--dhcpv6/ztpv6/parse_vendor_options.go19
-rw-r--r--dhcpv6/ztpv6/parse_vendor_options_test.go23
3 files changed, 38 insertions, 5 deletions
diff --git a/dhcpv6/ztpv6/README.md b/dhcpv6/ztpv6/README.md
index f44191b..a3e16f8 100644
--- a/dhcpv6/ztpv6/README.md
+++ b/dhcpv6/ztpv6/README.md
@@ -3,6 +3,7 @@
## Currently Supported Vendors For DHCPv6 ZTP
- Arista
- ZPE
+ - Ciena
## Why Do We Need This?
Many network hardware vendors support features that allow network devices to provision themselves with proper supporting automation/tools. Network devices can rely on DHCP and other methods to gather bootfile info, IPs, etc. DHCPv6 Vendor options provides us Vendor Name, Make, Model, and Serial Number data. This data can be used to uniquely identify individual network devices at provisioning time and can be used by tooling to make decisions necessary to correctly and reliably provision a network device.
diff --git a/dhcpv6/ztpv6/parse_vendor_options.go b/dhcpv6/ztpv6/parse_vendor_options.go
index 212733c..3d1fd01 100644
--- a/dhcpv6/ztpv6/parse_vendor_options.go
+++ b/dhcpv6/ztpv6/parse_vendor_options.go
@@ -2,9 +2,11 @@ package ztpv6
import (
"errors"
+ "strconv"
"strings"
"github.com/insomniacslk/dhcp/dhcpv6"
+ "github.com/insomniacslk/dhcp/iana"
)
var (
@@ -66,6 +68,23 @@ func ParseVendorData(packet dhcpv6.DHCPv6) (*VendorData, error) {
vd.Model = p[1]
vd.Serial = p[2]
return &vd, nil
+
+ // For Ciena the class identifier (opt 60) is written in the following format:
+ // {vendor iana code}-{product}-{type}
+ // For Ciena the iana code is 1271
+ // The product type is a number that maps to a Ciena product
+ // The type is used to identified different subtype of the product.
+ // An example can be ‘1271-23422Z11-123’.
+ case strings.HasPrefix(d, strconv.Itoa(int(iana.EnterpriseIDCienaCorporation))):
+ v := strings.Split(d, "-")
+ if len(v) < 3 {
+ return nil, errVendorOptionMalformed
+ }
+ duid := packet.(*dhcpv6.Message).Options.ClientID()
+ vd.VendorName = iana.EnterpriseIDCienaCorporation.String()
+ vd.Model = v[1] + "-" + v[2]
+ vd.Serial = string(duid.EnterpriseIdentifier)
+ return &vd, nil
}
}
return nil, errors.New("failed to parse vendor option data")
diff --git a/dhcpv6/ztpv6/parse_vendor_options_test.go b/dhcpv6/ztpv6/parse_vendor_options_test.go
index 45b42d6..cd2fb3d 100644
--- a/dhcpv6/ztpv6/parse_vendor_options_test.go
+++ b/dhcpv6/ztpv6/parse_vendor_options_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/insomniacslk/dhcp/dhcpv6"
+ "github.com/insomniacslk/dhcp/iana"
"github.com/stretchr/testify/require"
)
@@ -56,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},
@@ -74,6 +76,15 @@ func TestParseVendorDataWithVendorClass(t *testing.T) {
vc: "ZPESystems:NSC:001234567",
want: &VendorData{VendorName: "ZPESystems", Model: "NSC", 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"},
+ },
}
for _, tc := range tt {
@@ -85,7 +96,9 @@ func TestParseVendorDataWithVendorClass(t *testing.T) {
packet.AddOption(&dhcpv6.OptVendorClass{
EnterpriseNumber: 0000, Data: [][]byte{[]byte(tc.vc)}})
-
+ 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)