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) }
func sendLLDP(deviceID string, f openflow.Factory, w trans.Writer, p openflow.Port) error { lldp, err := newLLDPEtherFrame(deviceID, p) if err != nil { return err } outPort := openflow.NewOutPort() outPort.SetValue(p.Number()) // Packet out to the port action, err := f.NewAction() if err != nil { return err } action.SetOutPort(outPort) out, err := f.NewPacketOut() if err != nil { return err } // From controller out.SetInPort(openflow.NewInPort()) out.SetAction(action) out.SetData(lldp) return w.Write(out) }
func (r *Action) UnmarshalBinary(data []byte) error { buf := data for len(buf) >= 4 { t := binary.BigEndian.Uint16(buf[0:2]) length := binary.BigEndian.Uint16(buf[2:4]) if len(buf) < int(length) { return openflow.ErrInvalidPacketLength } switch t { case OFPAT_OUTPUT: if len(buf) < 8 { return openflow.ErrInvalidPacketLength } outPort := openflow.NewOutPort() outPort.SetValue(binary.BigEndian.Uint32(buf[4:8])) r.SetOutPort(outPort) if err := r.Error(); err != nil { return err } case OFPAT_SET_FIELD: if len(buf) < 8 { return openflow.ErrInvalidPacketLength } header := binary.BigEndian.Uint32(buf[4:8]) class := header >> 16 & 0xFFFF if class != 0x8000 { return errors.New("unsupported TLV class") } field := header >> 9 & 0x7F switch field { case OFPXMT_OFB_ETH_DST: if len(buf) < 14 { return openflow.ErrInvalidPacketLength } r.SetDstMAC(buf[8:14]) if err := r.Error(); err != nil { return err } case OFPXMT_OFB_ETH_SRC: if len(buf) < 14 { return openflow.ErrInvalidPacketLength } r.SetSrcMAC(buf[8:14]) if err := r.Error(); err != nil { return err } default: // Do nothing } default: // Do nothing } buf = buf[length:] } return nil }
func (r *Device) SendARPAnnouncement(ip net.IP, mac net.HardwareAddr) error { // Write lock r.mutex.Lock() defer r.mutex.Unlock() if r.closed { return ErrClosedDevice } announcement, err := makeARPAnnouncement(ip, mac) if err != nil { return err } inPort := openflow.NewInPort() inPort.SetController() action, err := r.factory.NewAction() if err != nil { return err } // Flood action.SetOutPort(openflow.NewOutPort()) out, err := r.factory.NewPacketOut() if err != nil { return err } out.SetInPort(inPort) out.SetAction(action) out.SetData(announcement) return r.session.Write(out) }
func (r *Device) RemoveAllFlows() error { // Write lock r.mutex.Lock() defer r.mutex.Unlock() if r.closed { return ErrClosedDevice } // Wildcard match match, err := r.factory.NewMatch() if err != nil { return err } // Set output port to OFPP_NONE port := openflow.NewOutPort() port.SetNone() flowmod, err := r.factory.NewFlowMod(openflow.FlowDelete) if err != nil { return err } // Remove flows except the table miss flows (Note that MSB of the cookie is a marker) flowmod.SetCookieMask(0x1 << 63) flowmod.SetTableID(0xFF) // ALL flowmod.SetFlowMatch(match) flowmod.SetOutPort(port) if err := r.session.Write(flowmod); err != nil { return err } return setARPSender(r.factory, r.session.trans) }
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) }
func (r *L2Switch) installFlow(p flowParam) error { // Skip the installation if p is already installed if r.cache.exist(p) { r.log.Debug(fmt.Sprintf("L2Switch: skipping duplicated flow installation: deviceID=%v, dstMAC=%v, outPort=%v", p.device.ID(), p.dstMAC, p.outPort)) return nil } f := p.device.Factory() match, err := f.NewMatch() if err != nil { return err } match.SetVLANID(r.vlanID) match.SetDstMAC(p.dstMAC) outPort := openflow.NewOutPort() outPort.SetValue(p.outPort) action, err := f.NewAction() if err != nil { return err } action.SetOutPort(outPort) inst, err := f.NewInstruction() if err != nil { return err } inst.ApplyAction(action) flow, err := f.NewFlowMod(openflow.FlowAdd) if err != nil { return err } flow.SetTableID(p.device.FlowTableID()) flow.SetIdleTimeout(30) flow.SetPriority(10) flow.SetFlowMatch(match) flow.SetFlowInstruction(inst) if err := p.device.SendMessage(flow); err != nil { return err } barrier, err := f.NewBarrierRequest() if err != nil { return err } if err := p.device.SendMessage(barrier); err != nil { return err } r.cache.add(p) r.log.Debug(fmt.Sprintf("L2Switch: added a flow cache entry: deviceID=%v, dstMAC=%v, outPort=%v", p.device.ID(), p.dstMAC, p.outPort)) return nil }
func NewFlowMod(xid uint32, cmd uint16) openflow.FlowMod { // Default out_port value is OFPP_NONE (OFPP_ANY) outPort := openflow.NewOutPort() outPort.SetNone() return &FlowMod{ Message: openflow.NewMessage(openflow.OF10_VERSION, OFPT_FLOW_MOD, xid), command: cmd, outPort: outPort, } }
func sendQueueConfigRequest(f openflow.Factory, w trans.Writer, port uint32) error { msg, err := f.NewQueueGetConfigRequest() if err != nil { return err } p := openflow.NewOutPort() p.SetValue(port) msg.SetPort(p) return w.Write(msg) }
func (r *Controller) removeFlows(mac net.HardwareAddr) { for _, sw := range r.topo.Devices() { f := sw.Factory() match, err := f.NewMatch() if err != nil { r.log.Err(fmt.Sprintf("Controller: REST: failed to create an OpenFlow match: %v", err)) continue } match.SetDstMAC(mac) outPort := openflow.NewOutPort() outPort.SetNone() r.log.Debug(fmt.Sprintf("Controller: REST: removing flows whose destinatcion MAC address is %v on %v", mac, sw.ID())) if err := sw.RemoveFlow(match, outPort); err != nil { r.log.Err(fmt.Sprintf("Controller: REST: failed to remove a flow from %v: %v", sw.ID(), err)) continue } } }
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) }
func setARPSender(f openflow.Factory, w trans.Writer) error { match, err := f.NewMatch() if err != nil { return err } match.SetEtherType(0x0806) // ARP outPort := openflow.NewOutPort() outPort.SetController() action, err := f.NewAction() if err != nil { return err } action.SetOutPort(outPort) inst, err := f.NewInstruction() if err != nil { return err } inst.ApplyAction(action) flow, err := f.NewFlowMod(openflow.FlowAdd) if err != nil { return err } // Permanent flow flow.SetIdleTimeout(0) flow.SetHardTimeout(0) flow.SetPriority(100) flow.SetFlowMatch(match) flow.SetFlowInstruction(inst) if err := w.Write(flow); err != nil { return err } return sendBarrierRequest(f, w) }
func (r *of13Session) setDefaultTableMiss(f openflow.Factory, w trans.Writer) error { inst, err := f.NewInstruction() if err != nil { return err } // 0 -> Controller outPort := openflow.NewOutPort() outPort.SetController() action, err := f.NewAction() if err != nil { return err } action.SetOutPort(outPort) inst.ApplyAction(action) if err := r.setTableMiss(f, w, 0, inst); err != nil { return fmt.Errorf("failed to set table_miss flow entry: %v", err) } r.device.setFlowTableID(0) return nil }
func (r *of13Session) setHP2920TableMiss(f openflow.Factory, w trans.Writer) error { // Table-100 is a hardware table, and Table-200 is a software table // that has very low performance. inst, err := f.NewInstruction() if err != nil { return err } // 0 -> 100 inst.GotoTable(100) if err := r.setTableMiss(f, w, 0, inst); err != nil { return fmt.Errorf("failed to set table_miss flow entry: %v", err) } // 100 -> 200 inst.GotoTable(200) if err := r.setTableMiss(f, w, 100, inst); err != nil { return fmt.Errorf("failed to set table_miss flow entry: %v", err) } // 200 -> Controller outPort := openflow.NewOutPort() outPort.SetController() action, err := f.NewAction() if err != nil { return err } action.SetOutPort(outPort) inst.ApplyAction(action) if err := r.setTableMiss(f, w, 200, inst); err != nil { return fmt.Errorf("failed to set table_miss flow entry: %v", err) } r.device.setFlowTableID(200) return nil }
func (r *Action) UnmarshalBinary(data []byte) error { buf := data for len(buf) >= 4 { t := binary.BigEndian.Uint16(buf[0:2]) length := binary.BigEndian.Uint16(buf[2:4]) if len(buf) < int(length) { return openflow.ErrInvalidPacketLength } switch t { case OFPAT_OUTPUT: if len(buf) < 8 { return openflow.ErrInvalidPacketLength } outPort := openflow.NewOutPort() outPort.SetValue(uint32(binary.BigEndian.Uint16(buf[4:6]))) r.SetOutPort(outPort) if err := r.Error(); err != nil { return err } case OFPAT_SET_DL_SRC: if len(buf) < 16 { return openflow.ErrInvalidPacketLength } r.SetSrcMAC(buf[4:10]) if err := r.Error(); err != nil { return err } case OFPAT_SET_DL_DST: if len(buf) < 16 { return openflow.ErrInvalidPacketLength } r.SetDstMAC(buf[4:10]) if err := r.Error(); err != nil { return err } case OFPAT_ENQUEUE: if len(buf) < 16 { return openflow.ErrInvalidPacketLength } outPort := openflow.NewOutPort() outPort.SetValue(uint32(binary.BigEndian.Uint16(buf[4:6]))) r.SetOutPort(outPort) r.SetQueue(binary.BigEndian.Uint32(buf[12:16])) if err := r.Error(); err != nil { return err } case OFPAT_SET_VLAN_VID: if len(buf) < 8 { return openflow.ErrInvalidPacketLength } r.SetVLANID(binary.BigEndian.Uint16(buf[4:6])) if err := r.Error(); err != nil { return err } default: // Do nothing } buf = buf[length:] } return nil }