Example #1
0
func (r *L2Switch) OnTopologyChange(finder network.Finder) error {
	r.log.Debug("L2Switch: OnTopologyChange..")

	// We should remove all edges from all switch devices when the network topology is changed.
	// Otherwise, installed flow rules in switches may result in incorrect packet routing based on the previous topology.
	if err := r.removeAllFlows(finder.Devices()); err != nil {
		return err
	}

	return r.BaseProcessor.OnTopologyChange(finder)
}
Example #2
0
func (r *ProxyARP) broadcastARPAnnouncement(finder network.Finder, vips []VIP) {
	for _, v := range vips {
		for _, d := range finder.Devices() {
			if err := d.SendARPAnnouncement(v.Address, v.MAC); err != nil {
				r.log.Err(fmt.Sprintf("ProxyARP: failed to broadcast ARP announcement: %v", err))
				continue
			}
		}
		r.log.Info(fmt.Sprintf("ProxyARP: toggled VIP %v to %v", v.Address, v.MAC))
	}
}
Example #3
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)
}