func decodeLLDP(b []byte) (nom.Node, nom.Port, error) { h := lldp.NewLinkDiscoveryProtocolWithBuf(b) size := h.Size() tlvb := b[size:] chTLV := lldp.NewChassisMacTLVWithBuf(tlvb) if chTLV.Size() == 0 { return nom.Node{}, nom.Port{}, errors.New("decodeLLDP: no chassis id") } n := nom.Node{ MACAddr: chTLV.MacAddr(), } size += chTLV.Size() tlvb = b[size:] pTLV := lldp.NewLinkDiscoveryTLVWithBuf(tlvb) if pTLV.Size() == 0 || pTLV.Type() != uint8(lldp.TLV_PORT_ID) { return nom.Node{}, nom.Port{}, errors.New("decodeLLDP: no port id") } v := pTLV.Value() if v[0] != uint8(lldp.PORT_TLV_IFACE_NAME) { return nom.Node{}, nom.Port{}, errors.New("decodeLLDP: no port iface name") } portUID := nom.UID(v[1:]) nID, pID := nom.ParsePortUID(portUID) n.ID = nID return n, nom.Port{ID: pID, Node: n.UID()}, nil }
func encodeLLDP(n nom.Node, p nom.Port) []byte { b := make([]byte, 256) h := lldp.NewLinkDiscoveryProtocolWithBuf(b) h.Init() h.SetSrcMac(n.MACAddr) h.SetDstMac([6]byte{0x01, 0x80, 0xC2, 0x00, 0x00, 0x0E}) size := h.Size() tlvb := b[size:] chTLV := lldp.NewChassisMacTLVWithBuf(tlvb) chTLV.Init() chTLV.SetMacAddr(n.MACAddr) size += chTLV.Size() tlvb = b[size:] pTLV := lldp.NewLinkDiscoveryTLVWithBuf(tlvb) pTLV.Init() pTLV.SetType(uint8(lldp.TLV_PORT_ID)) pTLV.AddValue(byte(lldp.PORT_TLV_IFACE_NAME)) for _, v := range []byte(p.UID()) { pTLV.AddValue(v) } size += pTLV.Size() tlvb = b[size:] ttlTLV := lldp.NewLinkDiscoveryTLVWithBuf(tlvb) ttlTLV.Init() ttlTLV.SetType(uint8(lldp.TLV_TTL)) ttlTLV.AddValue(0) ttlTLV.AddValue(0xFF) size += ttlTLV.Size() tlvb = b[size:] endTLV := lldp.NewLinkDiscoveryTLVWithBuf(tlvb) endTLV.Init() endTLV.SetTypeAndLen(0) size += ttlTLV.Size() // TODO(soheil): Maybe add a few custom fields? return b[:size] }