Ejemplo n.º 1
0
func (r *ProxyARP) OnPacketIn(finder network.Finder, ingress *network.Port, eth *protocol.Ethernet) error {
	// ARP?
	if eth.Type != 0x0806 {
		return r.BaseProcessor.OnPacketIn(finder, ingress, eth)
	}

	r.log.Debug(fmt.Sprintf("ProxyARP: received ARP packet.. ingress=%v, srcEthMAC=%v, dstEthMAC=%v", ingress.ID(), eth.SrcMAC, eth.DstMAC))

	arp := new(protocol.ARP)
	if err := arp.UnmarshalBinary(eth.Payload); err != nil {
		return err
	}
	// Drop ARP announcement
	if isARPAnnouncement(arp) {
		// We don't allow a host sends ARP announcement to the network. This controller only can send it,
		// and we will flood the announcement to all switch devices using PACKET_OUT  when we need it.
		r.log.Info(fmt.Sprintf("ProxyARP: drop ARP announcements.. ingress=%v (%v)", ingress.ID(), arp))
		return nil
	}
	// ARP request?
	if arp.Operation != 1 {
		// Drop all ARP packets whose type is not a reqeust.
		r.log.Info(fmt.Sprintf("ProxyARP: drop ARP packet whose type is not a request.. ingress=%v (%v)", ingress.ID(), arp))
		return nil
	}

	mac, ok, err := r.db.MAC(arp.TPA)
	if err != nil {
		return err
	}
	if !ok {
		r.log.Debug(fmt.Sprintf("ProxyARP: drop the ARP request for unknown host (%v)", arp.TPA))
		// Unknown hosts. Drop the packet.
		return nil
	}
	r.log.Debug(fmt.Sprintf("ProxyARP: ARP request for %v (%v)", arp.TPA, mac))

	reply, err := makeARPReply(arp, mac)
	if err != nil {
		return err
	}
	r.log.Debug(fmt.Sprintf("ProxyARP: sending ARP reply to %v..", ingress.ID()))

	return sendARPReply(ingress, reply)
}
Ejemplo n.º 2
0
func (r *flooder) flood(ingress *network.Port, packet []byte) error {
	f := ingress.Device().Factory()

	inPort := openflow.NewInPort()
	inPort.SetValue(ingress.Number())

	outPort := openflow.NewOutPort()
	outPort.SetFlood()

	action, err := f.NewAction()
	if err != nil {
		return err
	}
	action.SetOutPort(outPort)

	out, err := f.NewPacketOut()
	if err != nil {
		return err
	}
	out.SetInPort(inPort)
	out.SetAction(action)
	out.SetData(packet)

	return ingress.Device().SendMessage(out)
}
Ejemplo n.º 3
0
func (r *BaseProcessor) PacketOut(egress *network.Port, packet []byte) error {
	f := egress.Device().Factory()

	inPort := openflow.NewInPort()
	inPort.SetController()

	outPort := openflow.NewOutPort()
	outPort.SetValue(egress.Number())

	action, err := f.NewAction()
	if err != nil {
		return err
	}
	action.SetOutPort(outPort)

	out, err := f.NewPacketOut()
	if err != nil {
		return err
	}
	out.SetInPort(inPort)
	out.SetAction(action)
	out.SetData(packet)

	return egress.Device().SendMessage(out)
}
Ejemplo n.º 4
0
func (r *ProxyARP) OnPortDown(finder network.Finder, port *network.Port) error {
	dpid, err := strconv.ParseUint(port.Device().ID(), 10, 64)
	if err != nil {
		r.log.Err(fmt.Sprintf("ProxyARP: invalid switch DPID: %v", port.Device().ID()))
		return r.BaseProcessor.OnPortDown(finder, port)
	}
	vips, err := r.db.TogglePortVIP(dpid, uint16(port.Number()))
	if err != nil {
		r.log.Err(fmt.Sprintf("ProxyARP: failed to toggle VIP hosts: %v", err))
		return r.BaseProcessor.OnPortDown(finder, port)
	}
	r.broadcastARPAnnouncement(finder, vips)

	return r.BaseProcessor.OnPortDown(finder, port)
}
Ejemplo n.º 5
0
func (r *L2Switch) OnPortDown(finder network.Finder, port *network.Port) error {
	r.log.Debug(fmt.Sprintf("L2Switch: port down! removing all flows heading to that port (%v)..", port.ID()))

	device := port.Device()
	factory := device.Factory()
	// Wildcard match
	match, err := factory.NewMatch()
	if err != nil {
		return err
	}
	outPort := openflow.NewOutPort()
	outPort.SetValue(port.Number())

	if err := device.RemoveFlow(match, outPort); err != nil {
		return fmt.Errorf("removing flows heading to port %v: %v", port.ID(), err)
	}

	return r.BaseProcessor.OnPortDown(finder, port)
}
Ejemplo n.º 6
0
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)
}