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) }
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)) } }
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) }