func makeARPReply(request *protocol.ARP, mac net.HardwareAddr) ([]byte, error) { v := protocol.NewARPReply(mac, request.SHA, request.TPA, request.SPA) reply, err := v.MarshalBinary() if err != nil { return nil, err } eth := protocol.Ethernet{ SrcMAC: mac, DstMAC: request.SHA, Type: 0x0806, Payload: reply, } return eth.MarshalBinary() }
func makeARPAnnouncement(ip net.IP, mac net.HardwareAddr) ([]byte, error) { v := protocol.NewARPRequest(mac, ip, ip) anon, err := v.MarshalBinary() if err != nil { return nil, err } eth := protocol.Ethernet{ SrcMAC: mac, DstMAC: net.HardwareAddr([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}), Type: 0x0806, Payload: anon, } return eth.MarshalBinary() }
func (r *L2Switch) processPacket(finder network.Finder, ingress *network.Port, eth *protocol.Ethernet) (drop bool, err error) { r.log.Debug(fmt.Sprintf("L2Switch: PACKET_IN.. Ingress=%v, SrcMAC=%v, DstMAC=%v", ingress.ID(), eth.SrcMAC, eth.DstMAC)) packet, err := eth.MarshalBinary() if err != nil { return false, err } // Broadcast? if isBroadcast(eth) { r.log.Debug(fmt.Sprintf("L2Switch: broadcasting.. SrcMAC=%v, DstMAC=%v", eth.SrcMAC, eth.DstMAC)) return true, r.stormCtrl.broadcast(ingress, packet) } dstNode, err := finder.Node(eth.DstMAC) if err != nil { return true, fmt.Errorf("locating a node (MAC=%v): %v", eth.DstMAC, err) } // Unknown node? if dstNode == nil { r.log.Debug(fmt.Sprintf("L2Switch: unknown node! dropping.. SrcMAC=%v, DstMAC=%v", eth.SrcMAC, eth.DstMAC)) return true, nil } // Disconnected node? port := dstNode.Port().Value() if port.IsPortDown() || port.IsLinkDown() { r.log.Debug(fmt.Sprintf("L2Switch: disconnected node! dropping.. SrcMAC=%v, DstMAC=%v", eth.SrcMAC, eth.DstMAC)) return true, nil } param := switchParam{} // Check whether src and dst nodes reside on a same switch device if ingress.Device().ID() == dstNode.Port().Device().ID() { param = switchParam{ finder: finder, ethernet: eth, ingress: ingress, egress: dstNode.Port(), rawPacket: packet, } } else { path := finder.Path(ingress.Device().ID(), dstNode.Port().Device().ID()) if len(path) == 0 { r.log.Debug(fmt.Sprintf("L2Switch: empty path.. dropping SrcMAC=%v, DstMAC=%v", eth.SrcMAC, eth.DstMAC)) return true, nil } egress := path[0][0] // Drop this packet if it goes back to the ingress port to avoid duplicated packet routing if ingress.Number() == egress.Number() { r.log.Debug(fmt.Sprintf("L2Switch: ignore routing path that goes back to the ingress port (SrcMAC=%v, DstMAC=%v)", eth.SrcMAC, eth.DstMAC)) return true, nil } param = switchParam{ finder: finder, ethernet: eth, ingress: ingress, egress: egress, rawPacket: packet, } } return true, r.switching(param) }