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 sendLLDPPacket(n nom.Node, p nom.Port, ctx bh.RcvContext) { pkt := nom.PacketOut{ Node: n.UID(), Packet: nom.Packet(encodeLLDP(n, p)), BufferID: 0xFFFFFFFF, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p.UID()}, }, }, } ctx.Emit(pkt) }
func TestLLDPEncode(t *testing.T) { node := nom.Node{ ID: "n1", MACAddr: [6]byte{1, 2, 3, 4, 5, 6}, } port := nom.Port{ ID: "1", Name: "if1", MACAddr: [6]byte{1, 2, 3, 4, 5, 7}, Node: node.UID(), } b := encodeLLDP(node, port) //for i := 0; i < len(b); i += 12 { //j := 0 //for ; j < 12 && i+j < len(b); j++ { //fmt.Printf("%02X ", b[i+j]) //} //for k := j; k < 12; k++ { //fmt.Print(" ") //} //fmt.Printf("\t%s\n", strconv.QuoteToASCII(string(b[i:i+j]))) //} decN, decP, err := decodeLLDP(b) if err != nil { t.Errorf("Cannot decode LLDP: %v", err) } if decN.ID != node.ID { t.Errorf("Invalid node ID decoded: %v != %v", decN.ID, node.ID) } if decN.MACAddr != node.MACAddr { t.Errorf("Invalid node MAC decoded: %v != %v", decN.MACAddr, node.MACAddr) } if decP.ID != port.ID { t.Errorf("Invalid port ID decoded: %v != %v", decP.ID, port.ID) } }