コード例 #1
0
ファイル: switch.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #2
0
ファイル: session.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #3
0
ファイル: action.go プロジェクト: yebinMoon/cherry
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
}
コード例 #4
0
ファイル: device.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #5
0
ファイル: device.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #6
0
ファイル: processor.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #7
0
ファイル: switch.go プロジェクト: yebinMoon/cherry
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
}
コード例 #8
0
ファイル: flow_mod.go プロジェクト: yebinMoon/cherry
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,
	}
}
コード例 #9
0
ファイル: session.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #10
0
ファイル: controller.go プロジェクト: yebinMoon/cherry
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
		}
	}
}
コード例 #11
0
ファイル: switch.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #12
0
ファイル: session.go プロジェクト: yebinMoon/cherry
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)
}
コード例 #13
0
ファイル: of13_session.go プロジェクト: yebinMoon/cherry
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
}
コード例 #14
0
ファイル: of13_session.go プロジェクト: yebinMoon/cherry
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
}
コード例 #15
0
ファイル: action.go プロジェクト: yebinMoon/cherry
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
}