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 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() // TODO(soheil): Maybe add a few custom fields? return b[:size] }
func (d *of10Driver) handshake(c *ofConn) error { freq := of10.NewFeaturesRequest() if err := c.WriteHeader(freq.Header); err != nil { return err } c.Flush() glog.V(2).Info("%v sent features request to the switch", c.ctx) hdr, err := c.ReadHeader() if err != nil { return err } v10, err := of10.ToHeader10(hdr) if err != nil { return err } frep, err := of10.ToFeaturesReply(v10) if err != nil { return err } glog.Infof("%v completes handshaking with switch %016x", c.ctx, frep.DatapathId()) glog.Infof("%v disables packet buffers in switch %016x", c.ctx, frep.DatapathId()) cfg := of10.NewSwitchSetConfig() cfg.SetMissSendLen(0xFFFF) c.WriteHeader(cfg.Header) nodeID := datapathIDToNodeID(frep.DatapathId()) c.node = nom.Node{ ID: nodeID, MACAddr: datapathIDToMACAddr(frep.DatapathId()), Capabilities: nil, } glog.Infof("%v is connected to %v", c.ctx, c.node) nomDriver := nom.Driver{ BeeID: c.ctx.ID(), Role: nom.DriverRoleDefault, } c.ctx.Emit(nom.NodeConnected{ Node: c.node, Driver: nomDriver, }) d.ofPorts = make(map[uint16]*nom.Port) d.nomPorts = make(map[nom.UID]uint16) for _, p := range frep.Ports() { name := p.Name() port := nom.Port{ ID: portNoToPortID(uint32(p.PortNo())), Name: string(name[:]), MACAddr: p.HwAddr(), Node: c.NodeUID(), } d.ofPorts[p.PortNo()] = &port d.nomPorts[port.UID()] = p.PortNo() glog.Infof("%v added", port) if p.PortNo() <= uint16(of10.PP_MAX) { c.ctx.Emit(nom.PortStatusChanged{ Port: port, Driver: nomDriver, }) } } return nil }
func (d *of12Driver) handshake(c *ofConn) error { freq := of12.NewFeaturesRequest() if err := c.WriteHeader(freq.Header); err != nil { return err } c.Flush() glog.V(2).Info("Sent features request to the switch") hdr, err := c.ReadHeader() if err != nil { return err } v12, err := of12.ToHeader12(hdr) if err != nil { return err } frep, err := of12.ToFeaturesReply(v12) if err != nil { return err } glog.Infof("Handshake completed for switch %016x", frep.DatapathId()) glog.Infof("Disabling packet buffers in the switch.") cfg := of12.NewSwitchSetConfig() cfg.SetMissSendLen(0xFFFF) c.WriteHeader(cfg.Header) nodeID := datapathIDToNodeID(frep.DatapathId()) c.node = nom.Node{ ID: nodeID, MACAddr: datapathIDToMACAddr(frep.DatapathId()), Capabilities: []nom.NodeCapability{ nom.CapDriverRole, }, } nomDriver := nom.Driver{ BeeID: c.ctx.ID(), Role: nom.DriverRoleDefault, } c.ctx.Emit(nom.NodeConnected{ Node: c.node, Driver: nomDriver, }) d.ofPorts = make(map[uint32]*nom.Port) d.nomPorts = make(map[nom.UID]uint32) for _, p := range frep.Ports() { if p.PortNo() > uint32(of12.PP_MAX) { continue } name := p.Name() port := nom.Port{ ID: portNoToPortID(p.PortNo()), Name: string(name[:]), MACAddr: p.HwAddr(), Node: c.NodeUID(), } d.ofPorts[p.PortNo()] = &port d.nomPorts[port.UID()] = p.PortNo() glog.Infof("%v added", port) c.ctx.Emit(nom.PortStatusChanged{ Port: port, Driver: nomDriver, }) } return nil }