Beispiel #1
0
func (self match) UnmarshalBinary(msg []byte) error {
	exps := make(map[uint32]bool)
	for _, oxm := range ofp4.Oxm(msg).Iter() {
		hdr := oxm.Header()
		switch hdr.Class() {
		case ofp4.OFPXMC_OPENFLOW_BASIC:
			self[OxmKeyBasic(hdr.Type())] = OxmValueMask{
				Value: oxm.Value(),
				Mask:  oxm.Mask(),
			}
		case ofp4.OFPXMC_EXPERIMENTER:
			exps[ofp4.OxmExperimenterHeader(oxm).Experimenter()] = true
		default:
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_MATCH,
				ofp4.OFPBMC_BAD_TYPE,
			)
		}
	}
	for exp, _ := range exps {
		if handle, ok := oxmHandlers[exp]; ok {
			for k, v := range handle.Parse(msg) {
				oxmKeys[k] = exp
				self[k] = v
			}
		} else {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_MATCH,
				ofp4.OFPBRC_BAD_LEN,
			)
		}
	}
	return nil
}
Beispiel #2
0
func (entry *flowEntry) importInstructions(instructions ofp4.Instruction) error {
	for _, inst := range instructions.Iter() {
		switch inst.Type() {
		default:
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNKNOWN_INST,
			)
		case ofp4.OFPIT_GOTO_TABLE:
			entry.instGoto = ofp4.InstructionGotoTable(inst).TableId()
		case ofp4.OFPIT_WRITE_METADATA:
			i := ofp4.InstructionWriteMetadata(inst)
			if i.Metadata()&^i.MetadataMask() != 0 {
				return errors.New("invalid value/mask pair")
			}
			entry.instMetadata = &metadataInstruction{
				i.Metadata(),
				i.MetadataMask(),
			}
		case ofp4.OFPIT_WRITE_ACTIONS, ofp4.OFPIT_APPLY_ACTIONS, ofp4.OFPIT_CLEAR_ACTIONS:
			i := ofp4.InstructionActions(inst)
			switch inst.Type() {
			case ofp4.OFPIT_WRITE_ACTIONS:
				var aset actionSet
				if err := aset.UnmarshalBinary(i.Actions()); err != nil {
					return err
				}
				entry.instWrite = aset
			case ofp4.OFPIT_APPLY_ACTIONS:
				var alist actionList
				if err := alist.UnmarshalBinary(i.Actions()); err != nil {
					return err
				}
				entry.instApply = alist
			case ofp4.OFPIT_CLEAR_ACTIONS:
				entry.instClear = true
			}
		case ofp4.OFPIT_METER:
			entry.instMeter = ofp4.InstructionMeter(inst).MeterId()
		case ofp4.OFPIT_EXPERIMENTER:
			experimenter := ofp4.InstructionExperimenter(inst).Experimenter()
			data := inst[8:]
			if handler, ok := instructionHandlers[experimenter]; ok {
				pos := handler.Order(data)
				entry.instExp[pos] = append(entry.instExp[pos], instExperimenter{
					Experimenter: experimenter,
					Data:         data,
					Handler:      handler,
				})
			} else {
				return ofp4.MakeErrorMsg(ofp4.OFPET_BAD_INSTRUCTION, ofp4.OFPBIC_UNSUP_INST)
			}
		}
	}
	return nil
}
Beispiel #3
0
func (self *ofmMpPortStats) Map() Reducable {
	mpreq := ofp4.MultipartRequest(self.req)

	proc := func(portNo uint32, port gopenflow.Port) {
		var pstats gopenflow.PortStats
		var ethinfo gopenflow.PortStatsEthernet
		if p, err := port.Stats(); err != nil {
			log.Print(err)
		} else {
			pstats = p
			if p.Ethernet != nil {
				ethinfo = *p.Ethernet
			}
		}
		duration := self.pipe.portAlive[portNo].Total()
		chunk := ofp4.MakePortStats(
			portNo,
			pstats.RxPackets,
			pstats.TxPackets,
			pstats.RxBytes,
			pstats.TxBytes,
			pstats.RxDropped,
			pstats.TxDropped,
			pstats.RxErrors,
			pstats.TxErrors,
			ethinfo.RxFrameErr,
			ethinfo.RxOverErr,
			ethinfo.RxCrcErr,
			ethinfo.Collisions,
			uint32(duration.Seconds()),
			uint32(duration.Nanoseconds()%int64(time.Second)),
		)
		self.chunks = append(self.chunks, chunk)
	}

	portNo := ofp4.PortStatsRequest(mpreq.Body()).PortNo()
	switch portNo {
	default:
		if portNo > 0 && portNo <= ofp4.OFPP_MAX {
			if port := self.pipe.getPort(portNo); port != nil {
				proc(portNo, port)
			} else {
				self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_PORT_MOD_FAILED, ofp4.OFPPMFC_BAD_PORT))
			}
		} else {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_PORT_MOD_FAILED, ofp4.OFPPMFC_BAD_PORT))
		}
	case ofp4.OFPP_ALL, ofp4.OFPP_ANY:
		for portNo, port := range self.pipe.getAllPorts() {
			proc(portNo, port)
		}
	}
	return self
}
Beispiel #4
0
func (self *ofmPortMod) Map() Reducable {
	pipe := self.pipe
	msg := ofp4.PortMod(self.req)

	var confs []gopenflow.PortConfig
	for _, config := range []uint32{
		ofp4.OFPPC_PORT_DOWN,
		ofp4.OFPPC_NO_RECV,
		ofp4.OFPPC_NO_FWD,
		ofp4.OFPPC_NO_PACKET_IN,
	} {
		if msg.Mask()&config != 0 {
			switch config {
			case ofp4.OFPPC_PORT_DOWN:
				confs = append(confs, gopenflow.PortConfigPortDown(msg.Config()&config != 0))
			case ofp4.OFPPC_NO_RECV:
				confs = append(confs, gopenflow.PortConfigNoRecv(msg.Config()&config != 0))
			case ofp4.OFPPC_NO_FWD:
				confs = append(confs, gopenflow.PortConfigNoFwd(msg.Config()&config != 0))
			case ofp4.OFPPC_NO_PACKET_IN:
				confs = append(confs, gopenflow.PortConfigNoPacketIn(msg.Config()&config != 0))
			}
		}
	}
	// ofp_port_mod looks for normal port only.
	if port := pipe.getPort(msg.PortNo()); port != nil {
		port.SetConfig(confs)
	} else {
		self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_PORT_MOD_FAILED, ofp4.OFPPMFC_BAD_PORT))
	}
	return self
}
Beispiel #5
0
func (self actionSetField) Process(data *Frame) (*outputToPort, *outputToGroup, error) {
	ms := match{}
	if err := ms.UnmarshalBinary(self.Field); err != nil {
		return nil, nil, err
	} else {
		for oxmKey, oxmPayload := range ms {
			var handler OxmHandler
			switch oxmKey.(type) {
			case OxmKeyBasic:
				handler = oxmBasicHandler
			default:
				handler = oxmHandlers[oxmKeys[oxmKey]]
			}
			if handler == nil {
				return nil, nil, ofp4.MakeErrorMsg(
					ofp4.OFPBAC_BAD_EXPERIMENTER,
					ofp4.OFPBAC_BAD_TYPE,
				)
			} else if err := handler.SetField(data, oxmKey, oxmPayload); err != nil {
				return nil, nil, err
			}
		}
	}
	return nil, nil, nil
}
Beispiel #6
0
func (self *ofmGroupMod) Map() Reducable {
	pipe := self.pipe
	req := ofp4.GroupMod(self.req)

	switch req.Command() {
	case ofp4.OFPGC_ADD:
		if err := pipe.addGroup(req); err != nil {
			if e, ok := err.(ofp4.ErrorMsg); ok {
				self.putError(e)
			} else {
				log.Print(err)
			}
		}
	case ofp4.OFPGC_MODIFY:
		func() {
			pipe.lock.Lock()
			defer pipe.lock.Unlock()

			if group, exists := pipe.groups[req.GroupId()]; exists {
				var buckets bucketList
				if err := buckets.UnmarshalBinary(req.Buckets()); err != nil {
					log.Print(err)
				}
				group.groupType = req.Type()
				group.buckets = buckets
			} else {
				self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_GROUP_MOD_FAILED, ofp4.OFPGMFC_UNKNOWN_GROUP))
			}
		}()
	case ofp4.OFPGC_DELETE:
		if err := func() error {
			pipe.lock.Lock()
			defer pipe.lock.Unlock()

			if req.GroupId() == ofp4.OFPG_ALL {
				for groupId, _ := range pipe.groups {
					if err := pipe.deleteGroupInside(groupId); err != nil {
						return err
					}
				}
			} else {
				return pipe.deleteGroupInside(req.GroupId())
			}
			return nil
		}(); err != nil {
			if e, ok := err.(ofp4.ErrorMsg); ok {
				self.putError(e)
			} else {
				log.Print(err)
			}
		}
	}
	return self
}
Beispiel #7
0
func (self *ofmPacketOut) Map() Reducable {
	msg := ofp4.PacketOut(self.req)

	var eth []byte
	if msg.BufferId() == ofp4.OFP_NO_BUFFER {
		eth = msg.Data()
	} else {
		func() {
			self.pipe.lock.Lock()
			defer self.pipe.lock.Unlock()

			if original, ok := self.pipe.buffer[msg.BufferId()]; ok {
				delete(self.pipe.buffer, msg.BufferId())
				if data, err := original.Serialized(); err != nil {
					log.Print(err)
				} else {
					eth = data
				}
			} else {
				self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_BAD_REQUEST, ofp4.OFPBRC_BUFFER_UNKNOWN))
			}
		}()
	}
	if eth != nil {
		data := &Frame{
			serialized: eth,
			inPort:     msg.InPort(),
		}
		if data.inPort > 0 && data.inPort <= ofp4.OFPP_MAX {
			data.inPhyPort = self.pipe.getPort(msg.InPort()).PhysicalPort()
		}
		var actions actionList
		actions.UnmarshalBinary(msg.Actions())

		var gouts []outputToGroup
		for _, act := range []action(actions) {
			if pout, gout, e := act.Process(data); e != nil {
				log.Print(e)
			} else {
				if pout != nil {
					self.outputs = append(self.outputs, *pout)
				}
				if gout != nil {
					gouts = append(gouts, *gout)
				}
			}
		}
		self.outputs = append(self.outputs, self.pipe.groupToOutput(gouts, nil)...)
	}
	return self
}
Beispiel #8
0
func (self *ofmExperimenter) Map() Reducable {
	exp := ofp4.ExperimenterHeader(self.req)
	key := experimenterKey{
		Experimenter: exp.Experimenter(),
		ExpType:      exp.ExpType(),
	}
	if handler, ok := messageHandlers[key]; ok {
		for _, rep := range handler.Execute(exp[16:]) {
			msg := ofp4.MakeExperimenterHeader(exp.Experimenter(), exp.ExpType()).AppendData(rep).SetXid(self.req.Xid())
			self.resps = append(self.resps, msg)
		}
	} else {
		self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_BAD_REQUEST, ofp4.OFPBRC_BAD_EXPERIMENTER))
	}
	return self
}
Beispiel #9
0
func (pipe *Pipeline) deleteGroupInside(groupId uint32) error {
	if _, exists := pipe.groups[groupId]; exists {
		for _, chainId := range pipe.groupChains(groupId, nil) {
			if _, exists := pipe.groups[chainId]; exists {
				delete(pipe.groups, chainId)
			}
			pipe.filterFlowsInside(flowFilter{
				opUnregister: true,
				outPort:      ofp4.OFPP_ANY,
				outGroup:     chainId,
			})
		}
	} else {
		return ofp4.MakeErrorMsg(ofp4.OFPET_GROUP_MOD_FAILED, ofp4.OFPGMFC_GROUP_EXISTS)
	}
	return nil
}
Beispiel #10
0
/*
You should pass expanded match.
*/
func (self match) Conflict(target match) (bool, error) {
	uni := make(map[OxmKey]bool)
	for k, _ := range self {
		uni[k] = true
	}
	for k, _ := range target {
		uni[k] = true
	}

	for oxmKey, _ := range uni {
		if sPayload, ok := self[oxmKey]; !ok {
			continue
		} else if tPayload, ok := target[oxmKey]; !ok {
			continue
		} else {
			var handle OxmHandler
			switch k := oxmKey.(type) {
			case OxmKeyBasic:
				if oxm.Header(k).Class() == ofp4.OFPXMC_OPENFLOW_BASIC {
					handle = oxmBasicHandler
				}
			default:
				handle = oxmHandlers[oxmKeys[oxmKey]]
			}
			if handle == nil {
				return false, ofp4.MakeErrorMsg(
					ofp4.OFPET_BAD_MATCH,
					ofp4.OFPBMC_BAD_TYPE,
				)
			}
			if result, err := handle.Conflict(oxmKey, sPayload, tPayload); err != nil {
				return false, err
			} else if result {
				return true, nil
			}
		}
	}
	return false, nil
}
Beispiel #11
0
func (self match) Expand() (match, error) {
	var exps []uint32
	ret := make(map[OxmKey]OxmPayload)
	for k, v := range self {
		oxm := ofp4.Oxm(k.Bytes(v))
		if oxm.Header().Class() == ofp4.OFPXMC_EXPERIMENTER {
			exps = append(exps, ofp4.OxmExperimenterHeader(oxm).Experimenter())
		}
		ret[k] = v
	}
	oxmBasicHandler.Expand(ret)
	for _, exp := range exps {
		if handle, ok := oxmHandlers[exp]; !ok {
			return nil, ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_MATCH,
				ofp4.OFPBMC_BAD_TYPE,
			)
		} else if err := handle.Expand(ret); err != nil {
			return nil, err
		}
	}
	return ret, nil
}
Beispiel #12
0
func (pipe Pipeline) addFlowEntry(req ofp4.FlowMod) error {
	tableId := req.TableId()
	if tableId > ofp4.OFPTT_MAX {
		return ofp4.MakeErrorMsg(
			ofp4.OFPET_FLOW_MOD_FAILED,
			ofp4.OFPFMFC_BAD_TABLE_ID,
		)
	}
	pipe.lock.Lock()
	defer pipe.lock.Unlock()

	var table *flowTable
	if trial, ok := pipe.flows[tableId]; ok {
		table = trial
	} else {
		table = &flowTable{
			lock:    &sync.RWMutex{},
			feature: makeFlowTableFeature(),
		}
		pipe.flows[tableId] = table
	}
	return table.addFlowEntry(req, pipe)
}
Beispiel #13
0
func (pipe *Pipeline) addGroup(req ofp4.GroupMod) error {
	var buckets []bucket
	for _, msg := range req.Buckets().Iter() {
		var b bucket
		if err := b.UnmarshalBinary(msg); err != nil {
			return err
		}
		buckets = append(buckets, b)
	}

	pipe.lock.Lock()
	defer pipe.lock.Unlock()

	if _, exists := pipe.groups[req.GroupId()]; exists {
		return ofp4.MakeErrorMsg(ofp4.OFPET_GROUP_MOD_FAILED, ofp4.OFPGMFC_GROUP_EXISTS)
	} else {
		pipe.groups[req.GroupId()] = &group{
			lock:      &sync.RWMutex{},
			groupType: req.Type(),
			buckets:   buckets,
		}
	}
	return nil
}
Beispiel #14
0
func (self *ofmReply) createError(ofpet uint16, code uint16) {
	self.resps = append(self.resps,
		ofp4.Header(ofp4.MakeErrorMsg(ofpet, code)).AppendData(self.req).SetXid(self.req.Xid()))
}
Beispiel #15
0
func (self *flowTable) addFlowEntry(req ofp4.FlowMod, pipe Pipeline) error {
	flow, e1 := newFlowEntry(req)
	if e1 != nil {
		return e1
	}
	if err := self.feature.accepts(flow, req.Priority()); err != nil {
		return err
	}

	self.lock.Lock()
	defer self.lock.Unlock()

	var priority *flowPriority
	i := sort.Search(len(self.priorities), func(k int) bool {
		return self.priorities[k].priority <= req.Priority() // descending order
	})
	if i == len(self.priorities) || self.priorities[i].priority != req.Priority() {
		priority = &flowPriority{
			lock:     &sync.RWMutex{},
			priority: req.Priority(),
			flows:    make(map[uint32][]*flowEntry),
		}
		self.priorities = append(self.priorities, nil)
		copy(self.priorities[i+1:], self.priorities[i:])
		self.priorities[i] = priority
	} else {
		priority = self.priorities[i]
	}

	priority.lock.Lock()
	defer priority.lock.Unlock()

	key := priority.hash.Key(matchHash(flow.fields))

	flows := []*flowEntry{flow} // prepare for rebuild
	for k, fs := range priority.flows {
		if k == key {
			for _, f := range fs {
				if conflict, err := flow.fields.Conflict(f.fields); err != nil {
					return err
				} else if req.Flags()&ofp4.OFPFF_CHECK_OVERLAP != 0 && !conflict {
					return ofp4.MakeErrorMsg(ofp4.OFPET_FLOW_MOD_FAILED, ofp4.OFPFMFC_OVERLAP)
				}

				if isEqual, err := flow.fields.Equal(f.fields); err != nil {
					return err
				} else if isEqual {
					// old entry will be cleared
					if req.Flags()&ofp4.OFPFF_RESET_COUNTS == 0 {
						// counters should be copied
						flow.packetCount = f.packetCount
						flow.byteCount = f.byteCount
					}
				} else {
					flows = append(flows, f)
				}
			}
		} else {
			flows = append(flows, fs...)
		}
	}

	if portNo, act := hookDot11Action(req.Match().OxmFields()); portNo != 0 && len(act) != 0 {
		if port := pipe.getPort(portNo); port != nil {
			if err := port.Vendor(gopenflow.MgmtFrameAdd(act)).(error); err != nil {
				return err
			}
		}
	}
	priority.rebuildIndex(flows)
	self.activeCount = uint32(len(flows))
	return nil
}
Beispiel #16
0
func (self *ofmFlowMod) Map() Reducable {
	msg := ofp4.FlowMod(self.req)
	bufferId := msg.BufferId()

	switch msg.Command() {
	case ofp4.OFPFC_ADD:
		if err := self.pipe.addFlowEntry(msg); err != nil {
			if e, ok := err.(ofp4.ErrorMsg); ok {
				self.putError(e)
			} else {
				log.Print(err)
			}
		}
	case ofp4.OFPFC_MODIFY, ofp4.OFPFC_MODIFY_STRICT:
		reqMatch := match{}
		if err := reqMatch.UnmarshalBinary(msg.Match().OxmFields()); err != nil {
			log.Print(err)
		} else if msg.TableId() > ofp4.OFPTT_MAX {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_FLOW_MOD_FAILED, ofp4.OFPFMFC_BAD_TABLE_ID))
		} else {
			filter := flowFilter{
				cookie:     msg.Cookie(),
				cookieMask: msg.CookieMask(),
				tableId:    msg.TableId(),
				outPort:    ofp4.OFPP_ANY,
				outGroup:   ofp4.OFPG_ANY,
				match:      reqMatch,
			}
			if msg.Command() == ofp4.OFPFC_MODIFY_STRICT {
				filter.priority = msg.Priority()
				filter.opStrict = true
			}
			for _, stat := range self.pipe.filterFlows(filter) {
				flow := stat.flow
				if err := func() error {
					flow.lock.Lock()
					defer flow.lock.Unlock()

					if msg.Flags()&ofp4.OFPFF_RESET_COUNTS != 0 {
						flow.packetCount = 0
						flow.byteCount = 0
					}
					return flow.importInstructions(msg.Instructions())
				}(); err != nil {
					if e, ok := err.(ofp4.ErrorMsg); ok {
						self.putError(e)
					} else {
						log.Print(err)
					}
				}
			}
		}
	case ofp4.OFPFC_DELETE, ofp4.OFPFC_DELETE_STRICT:
		reqMatch := match{}
		if err := reqMatch.UnmarshalBinary(msg.Match().OxmFields()); err != nil {
			log.Print(err)
		} else {
			filter := flowFilter{
				opUnregister: true,
				cookie:       msg.Cookie(),
				cookieMask:   msg.CookieMask(),
				tableId:      msg.TableId(),
				outPort:      msg.OutPort(),
				outGroup:     msg.OutGroup(),
				match:        reqMatch,
			}
			if msg.Command() == ofp4.OFPFC_DELETE_STRICT {
				filter.priority = msg.Priority()
				filter.opStrict = true
			}
			for _, stat := range self.pipe.filterFlows(filter) {
				if hdr, err := stat.flow.fields.MarshalBinary(); err != nil {
					log.Print(err)
				} else if portNo, act := hookDot11Action(oxm.Oxm(hdr)); portNo != 0 && len(act) != 0 {
					if port := self.pipe.getPort(portNo); port != nil {
						if err := port.Vendor(gopenflow.MgmtFrameRemove(act)).(error); err != nil {
							log.Print(err)
						}
					}
				}
				if stat.flow.flags&ofp4.OFPFF_SEND_FLOW_REM != 0 {
					self.pipe.sendFlowRem(stat.tableId, stat.priority, stat.flow, ofp4.OFPRR_DELETE)
				}
			}
		}
		bufferId = ofp4.OFP_NO_BUFFER // nothing to do with buffer by specification.
	}
	if bufferId != ofp4.OFP_NO_BUFFER {
		original, ok := func() (outputToPort, bool) {
			self.pipe.lock.Lock()
			defer self.pipe.lock.Unlock()

			original, ok := self.pipe.buffer[bufferId]
			if ok {
				delete(self.pipe.buffer, bufferId)
			}
			return original, ok
		}()
		if ok {
			pipe := self.pipe
			pipe.datapath <- &flowTask{
				Frame:   original.Frame,
				pipe:    self.pipe,
				tableId: 0,
			}
		} else {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_BAD_REQUEST, ofp4.OFPBRC_BUFFER_UNKNOWN))
		}
	}
	return self
}
Beispiel #17
0
func (self *flowTableFeature) importProps(props ofp4.TableFeaturePropHeader) error {
	for _, prop := range props.Iter() {
		switch prop.Type() {
		case ofp4.OFPTFPT_INSTRUCTIONS, ofp4.OFPTFPT_INSTRUCTIONS_MISS:
			var ids []instructionKey
			for _, inst := range ofp4.TableFeaturePropInstructions(prop).InstructionIds().Iter() {
				if inst.Type() == ofp4.OFPIT_EXPERIMENTER {
					ids = append(ids, ofp4.InstructionExperimenter(inst).Experimenter())
				} else {
					ids = append(ids, inst.Type())
				}
			}
			switch prop.Type() {
			case ofp4.OFPTFPT_INSTRUCTIONS:
				self.hit.inst = ids
			case ofp4.OFPTFPT_INSTRUCTIONS_MISS:
				self.miss.inst = ids
			}
		case ofp4.OFPTFPT_NEXT_TABLES:
			self.hit.next = ofp4.TableFeaturePropNextTables(prop).NextTableIds()
		case ofp4.OFPTFPT_NEXT_TABLES_MISS:
			self.miss.next = ofp4.TableFeaturePropNextTables(prop).NextTableIds()
		case ofp4.OFPTFPT_WRITE_ACTIONS, ofp4.OFPTFPT_WRITE_ACTIONS_MISS,
			ofp4.OFPTFPT_APPLY_ACTIONS, ofp4.OFPTFPT_APPLY_ACTIONS_MISS:
			var ids []actionKey
			for _, act := range ofp4.TableFeaturePropActions(prop).ActionIds().Iter() {
				if act.Type() == ofp4.OFPAT_EXPERIMENTER {
					ids = append(ids, ofp4.ActionExperimenterHeader(act).Experimenter())
				} else {
					ids = append(ids, act.Type())
				}
			}
			switch prop.Type() {
			case ofp4.OFPTFPT_WRITE_ACTIONS:
				self.hit.writeActions = ids
			case ofp4.OFPTFPT_WRITE_ACTIONS_MISS:
				self.miss.writeActions = ids
			case ofp4.OFPTFPT_APPLY_ACTIONS:
				self.hit.applyActions = ids
			case ofp4.OFPTFPT_APPLY_ACTIONS_MISS:
				self.miss.applyActions = ids
			}
		case ofp4.OFPTFPT_MATCH, ofp4.OFPTFPT_WILDCARDS,
			ofp4.OFPTFPT_WRITE_SETFIELD, ofp4.OFPTFPT_WRITE_SETFIELD_MISS,
			ofp4.OFPTFPT_APPLY_SETFIELD, ofp4.OFPTFPT_APPLY_SETFIELD_MISS:
			var ids []oxmId
			for _, oxm := range ofp4.TableFeaturePropOxm(prop).OxmIds().Iter() {
				hdr := oxm.Header()
				if hdr.Class() == ofp4.OFPXMC_EXPERIMENTER {
					exp := ofp4.OxmExperimenterHeader(oxm).Experimenter()
					ids = append(ids, [...]uint32{oxmHandlers[exp].OxmId(uint32(oxm.Header())), exp})
				} else {
					ids = append(ids, hdr.Type())
				}
			}
			switch prop.Type() {
			case ofp4.OFPTFPT_MATCH:
				self.match = ids
			case ofp4.OFPTFPT_WILDCARDS:
				self.wildcards = ids
			case ofp4.OFPTFPT_WRITE_SETFIELD:
				self.hit.writeSetfield = ids
			case ofp4.OFPTFPT_WRITE_SETFIELD_MISS:
				self.miss.writeSetfield = ids
			case ofp4.OFPTFPT_APPLY_SETFIELD:
				self.hit.applySetfield = ids
			case ofp4.OFPTFPT_APPLY_SETFIELD_MISS:
				self.miss.applySetfield = ids
			}
		case ofp4.OFPTFPT_EXPERIMENTER, ofp4.OFPTFPT_EXPERIMENTER_MISS:
			msg := ofp4.TableFeaturePropExperimenter(prop)
			eKey := experimenterKey{
				Experimenter: msg.Experimenter(),
				ExpType:      msg.ExpType(),
			}
			if _, ok := tableHandlers[eKey]; !ok {
				return ofp4.MakeErrorMsg(
					ofp4.OFPET_TABLE_FEATURES_FAILED,
					ofp4.OFPTFFC_BAD_ARGUMENT,
				)
			}
			exp := experimenterProp{
				experimenterKey: eKey,
				Data:            msg.ExperimenterData(),
			}
			switch prop.Type() {
			case ofp4.OFPTFPT_EXPERIMENTER:
				self.hit.experimenter = append(self.hit.experimenter, exp)
			case ofp4.OFPTFPT_EXPERIMENTER_MISS:
				self.miss.experimenter = append(self.hit.experimenter, exp)
			}
		}
	}
	return nil
}
Beispiel #18
0
// See openflow switch 1.3.4 spec "Flow Table Modification Messages" page 40
func (self flowTableFeature) accepts(entry *flowEntry, priority uint16) error {
	isTableMiss := false
	if len(entry.fields) == 0 && priority == 0 {
		isTableMiss = true
	}

	var instKeys instructionKeyList
	if isTableMiss && self.miss.inst != nil {
		instKeys = instructionKeyList(self.miss.inst)
	} else if self.hit.inst != nil {
		instKeys = instructionKeyList(self.hit.inst)
	}

	if entry.instGoto != 0 {
		if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_GOTO_TABLE)) {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_INST,
			)
		}

		var next []uint8
		if isTableMiss && self.miss.next != nil {
			next = self.miss.next
		} else if self.hit.next != nil {
			next = self.hit.next
		}
		if next != nil {
			supported := false
			for _, tableId := range next {
				if entry.instGoto == tableId {
					supported = true
				}
			}
			if !supported {
				return ofp4.MakeErrorMsg(
					ofp4.OFPET_BAD_INSTRUCTION,
					ofp4.OFPBIC_BAD_TABLE_ID,
				)
			}
		}
	}

	if entry.instMetadata != nil {
		if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_WRITE_METADATA)) {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_INST,
			)
		}
		if entry.instMetadata.metadata&^self.metadataWrite != 0 {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_METADATA,
			)
		}
		if entry.instMetadata.mask&^self.metadataWrite != 0 {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_METADATA_MASK,
			)
		}
	}

	if !isTableMiss && self.match != nil {
		unavailable := func(id oxmId) bool {
			for _, k := range self.match {
				if k == id {
					return false
				}
			}
			return true
		}

		for k, p := range entry.fields {
			for _, oxm := range ofp4.Oxm(k.Bytes(p)).Iter() {
				var id oxmId
				hdr := oxm.Header()
				switch hdr.Type() {
				case ofp4.OFPXMC_OPENFLOW_BASIC:
					id = oxmBasicHandler.OxmId(uint32(hdr))
				case ofp4.OFPXMC_EXPERIMENTER:
					exp := ofp4.OxmExperimenterHeader(oxm).Experimenter()
					id = [...]uint32{
						oxmHandlers[exp].OxmId(uint32(hdr)),
						exp,
					}
				default:
					return ofp4.MakeErrorMsg(
						ofp4.OFPET_BAD_MATCH,
						ofp4.OFPBMC_BAD_TYPE,
					)
				}
				if unavailable(id) {
					return ofp4.MakeErrorMsg(
						ofp4.OFPET_BAD_MATCH,
						ofp4.OFPBMC_BAD_FIELD,
					)
				}
			}
		}

		for _, k := range self.wildcards {
			if unavailable(k) {
				return ofp4.MakeErrorMsg(
					ofp4.OFPET_BAD_MATCH,
					ofp4.OFPBMC_BAD_WILDCARDS,
				)
			}
		}
	}

	if len([]action(entry.instApply)) > 0 {
		if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_APPLY_ACTIONS)) {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_INST,
			)
		}
		var keys []actionKey
		if isTableMiss && self.miss.applyActions != nil {
			keys = self.miss.applyActions
		} else if self.hit.applyActions != nil {
			keys = self.hit.applyActions
		}
		if keys != nil {
			for _, act := range []action(entry.instApply) {
				aKey := act.Key()
				if !actionKeyList(keys).Have(aKey) {
					return ofp4.MakeErrorMsg(
						ofp4.OFPET_BAD_ACTION,
						ofp4.OFPBAC_BAD_TYPE,
					)
				}
			}
			// XXX: Experimenter
		}
	}

	if entry.instWrite.Len() > 0 {
		if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_WRITE_ACTIONS)) {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_INST,
			)
		}
		var keys []actionKey
		if isTableMiss && self.miss.writeActions != nil {
			keys = self.miss.writeActions
		} else if self.hit.writeActions != nil {
			keys = self.hit.writeActions
		}
		if keys != nil {
			for _, a := range entry.instWrite.hash {
				if !actionKeyList(keys).Have(a.Key()) {
					return ofp4.MakeErrorMsg(
						ofp4.OFPET_BAD_ACTION,
						ofp4.OFPBAC_BAD_TYPE,
					)
				}
			}
			for k, _ := range entry.instWrite.exp {
				if !actionKeyList(keys).Have(k) {
					return ofp4.MakeErrorMsg(
						ofp4.OFPET_BAD_ACTION,
						ofp4.OFPBAC_BAD_TYPE,
					)
				}
			}
		}
	}

	for _, insts := range entry.instExp {
		for _, inst := range insts {
			if instKeys != nil && !instKeys.Have(inst.Experimenter) {
				return ofp4.MakeErrorMsg(
					ofp4.OFPET_BAD_INSTRUCTION,
					ofp4.OFPBIC_UNSUP_INST,
				)
			}
		}
	}

	if entry.instMeter != 0 {
		if instKeys != nil && !instKeys.Have(uint16(ofp4.OFPIT_METER)) {
			return ofp4.MakeErrorMsg(
				ofp4.OFPET_BAD_INSTRUCTION,
				ofp4.OFPBIC_UNSUP_INST,
			)
		}
	}

	return nil
}
Beispiel #19
0
func (self *Pipeline) AddChannel(conn io.ReadWriteCloser) error {
	self.lock.Lock()
	defer self.lock.Unlock()

	ch := &channel{
		Conn: conn,
	}

	// process hello
	ch.Notify(ofp4.MakeHello(ofp4.MakeHelloElemVersionbitmap([]uint32{uint32(1 << 4)})))
	head := make([]byte, 4)
	if msg, err := readOfpMessage(conn, head); err != nil {
		return err
	} else if ofp4.Header(msg).Type() != ofp4.OFPT_HELLO {
		return fmt.Errorf("The first message must be HELLO")
	} else {
		satisfied := false
		for _, element := range ofp4.Hello(msg).Elements().Iter() {
			switch element.Type() {
			case ofp4.OFPHET_VERSIONBITMAP:
				bitmaps := ofp4.HelloElemVersionbitmap(element).Bitmaps()
				if len(bitmaps) > 0 && (bitmaps[0]&(1<<4) != 0) {
					satisfied = true
				}
				// ensure there be no bits higher than ofp4
				for i, b := range bitmaps {
					if i == 0 && (b&0xFFFFFFE0) != 0 {
						satisfied = false
					}
					if i > 0 && b != 0 {
						satisfied = false
					}
				}
			}
		}
		if !satisfied && ofp4.Header(msg).Version() == 4 {
			satisfied = true
		}
		if !satisfied {
			err := ofp4.MakeErrorMsg(
				ofp4.OFPET_HELLO_FAILED,
				ofp4.OFPHFC_INCOMPATIBLE,
			)
			ch.Response(ofp4.Header(err).SetXid(ofp4.Header(msg).Xid()))
			return err
		}
	}

	self.channels = append(self.channels, ch)

	worker := make(chan MapReducable)
	go MapReduce(worker, 4)
	go func() {
		defer close(worker)
		defer conn.Close()

		multipartCollect := make(map[uint32][][]byte)
		for {
			msg, err := readOfpMessage(conn, head)
			if err != nil {
				log.Print(err)
				break
			}
			reply := ofmReply{pipe: self, channel: ch, req: msg}
			switch ofp4.Header(msg).Type() {
			case ofp4.OFPT_ERROR:
				log.Print("got unexpected OFPT_ERROR")
			case ofp4.OFPT_ECHO_REQUEST:
				worker <- &ofmEcho{reply}
			case ofp4.OFPT_ECHO_REPLY:
				log.Print("got unexpected OFPT_ECHO_REPLY")
			case ofp4.OFPT_EXPERIMENTER:
				worker <- &ofmExperimenter{reply}
			case ofp4.OFPT_FEATURES_REQUEST:
				worker <- &ofmFeaturesRequest{reply}
			case ofp4.OFPT_GET_CONFIG_REQUEST:
				worker <- &ofmGetConfigRequest{reply}
			case ofp4.OFPT_SET_CONFIG:
				worker <- &ofmSetConfig{reply}
			case ofp4.OFPT_PACKET_OUT:
				worker <- &ofmPacketOut{ofmOutput{reply, nil}}
			case ofp4.OFPT_FLOW_MOD:
				worker <- &ofmFlowMod{ofmOutput{reply, nil}}
			case ofp4.OFPT_GROUP_MOD:
				worker <- &ofmGroupMod{reply}
			case ofp4.OFPT_PORT_MOD:
				worker <- &ofmPortMod{reply}
			case ofp4.OFPT_TABLE_MOD:
				worker <- &ofmTableMod{reply}
			case ofp4.OFPT_MULTIPART_REQUEST:
				xid := ofp4.Header(msg).Xid()
				req := ofp4.MultipartRequest(msg)

				multipartCollect[xid] = append(multipartCollect[xid], req.Body())
				if req.Flags()&ofp4.OFPMPF_REQ_MORE == 0 {
					reqs := multipartCollect[xid]
					delete(multipartCollect, xid)

					mreply := ofmMulti{
						ofmReply: reply,
						reqs:     reqs,
						chunks:   nil,
					}

					// capture
					switch req.Type() {
					case ofp4.OFPMP_DESC:
						worker <- &ofmMpDesc{mreply}
					case ofp4.OFPMP_TABLE:
						worker <- &ofmMpTable{mreply}
					case ofp4.OFPMP_GROUP_DESC:
						worker <- &ofmMpGroupDesc{mreply}
					case ofp4.OFPMP_GROUP_FEATURES:
						worker <- &ofmMpGroupFeatures{mreply}
					case ofp4.OFPMP_METER_FEATURES:
						worker <- &ofmMpMeterFeatures{mreply}
					case ofp4.OFPMP_PORT_DESC:
						worker <- &ofmMpPortDesc{mreply}
					case ofp4.OFPMP_FLOW:
						worker <- &ofmMpFlow{mreply}
					case ofp4.OFPMP_AGGREGATE:
						worker <- &ofmMpAggregate{mreply}
					case ofp4.OFPMP_PORT_STATS:
						worker <- &ofmMpPortStats{mreply}
					case ofp4.OFPMP_QUEUE:
						worker <- &ofmMpQueue{mreply}
					case ofp4.OFPMP_GROUP:
						worker <- &ofmMpGroup{mreply}
					case ofp4.OFPMP_METER:
						worker <- &ofmMpMeter{mreply}
					case ofp4.OFPMP_METER_CONFIG:
						worker <- &ofmMpMeterConfig{mreply}
					case ofp4.OFPMP_TABLE_FEATURES:
						worker <- &ofmMpTableFeatures{mreply}
					case ofp4.OFPMP_EXPERIMENTER:
						worker <- &ofmMpExperimenter{mreply}
					default:
						panic("unknown ofp_multipart_request.type")
					}
				}
			case ofp4.OFPT_BARRIER_REQUEST:
				for xid, _ := range multipartCollect {
					buf := ofp4.Header(make([]byte, 8))
					buf.SetXid(xid)
					rep := ofmReply{pipe: self, channel: ch, req: buf}
					rep.createError(ofp4.OFPET_BAD_REQUEST, ofp4.OFPBRC_BAD_MULTIPART)
					worker <- &rep
					delete(multipartCollect, xid)
				}
				worker <- &ofmBarrierRequest{reply}
			case ofp4.OFPT_QUEUE_GET_CONFIG_REQUEST:
				worker <- &ofmQueueGetConfigRequest{reply}
			case ofp4.OFPT_ROLE_REQUEST:
				worker <- &ofmRoleRequest{reply}
			case ofp4.OFPT_GET_ASYNC_REQUEST:
				worker <- &ofmGetAsyncRequest{reply}
			case ofp4.OFPT_SET_ASYNC:
				worker <- &ofmSetAsync{reply}
			case ofp4.OFPT_METER_MOD:
				worker <- &ofmMeterMod{reply}
			default:
				fmt.Printf("unknown ofp_header.type %v\n", msg)
				return
			}
		}
	}()
	return nil
}
Beispiel #20
0
func (self actionGeneric) Process(data *Frame) (*outputToPort, *outputToGroup, error) {
	switch self.Type {
	default:
		return nil, nil, ofp4.MakeErrorMsg(
			ofp4.OFPET_BAD_ACTION,
			ofp4.OFPBAC_BAD_TYPE,
		)
	case ofp4.OFPAT_COPY_TTL_OUT:
		var ttl uint8
		found := 0
		for _, layer := range data.Layers() {
			switch clayer := layer.(type) {
			case *layers.MPLS:
				ttl = clayer.TTL
				found++
			case *layers.IPv4:
				ttl = clayer.TTL
				found++
			case *layers.IPv6:
				ttl = clayer.HopLimit
				found++
			}
			if found == 2 {
				break // capture the second value
			}
		}
		if found > 1 {
			func() { // for direct exit from switch
				for _, layer := range data.layers {
					switch clayer := layer.(type) {
					case *layers.MPLS:
						clayer.TTL = ttl
						return
					case *layers.IPv4:
						clayer.TTL = ttl
						return
					case *layers.IPv6:
						clayer.HopLimit = ttl
						return
					}
				}
			}()
		}
	case ofp4.OFPAT_COPY_TTL_IN:
		var ttl uint8
		found := 0
		func() { // for direct exit from switch
			for _, layer := range data.Layers() {
				switch clayer := layer.(type) {
				case *layers.MPLS:
					if found > 0 {
						clayer.TTL = ttl
						return
					} else {
						ttl = clayer.TTL
						found++
					}
				case *layers.IPv4:
					if found > 0 {
						clayer.TTL = ttl
						return
					} else {
						ttl = clayer.TTL
						found++
					}
				case *layers.IPv6:
					if found > 0 {
						clayer.HopLimit = ttl
						return
					} else {
						ttl = clayer.HopLimit
						found++
					}
				}
			}
		}()
	case ofp4.OFPAT_DEC_MPLS_TTL:
		for _, layer := range data.layers {
			switch clayer := layer.(type) {
			case *layers.MPLS:
				if clayer.TTL > 0 {
					clayer.TTL--
				}
				if clayer.TTL == 0 {
					pout := &outputToPort{
						Frame:   data.clone(),
						outPort: ofp4.OFPP_CONTROLLER,
						reason:  ofp4.OFPR_INVALID_TTL,
					}
					// invalidate the frame
					data.serialized = data.serialized[:0]
					data.layers = nil
					return pout, nil, nil
				}
			}
		}
	case ofp4.OFPAT_POP_VLAN:
		var buf []gopacket.Layer
		found := false
		for i, layer := range data.Layers() {
			if found == false {
				var ethertype layers.EthernetType
				switch layer.LayerType() {
				case layers.LayerTypeDot1Q:
					ethertype = layer.(*layers.Dot1Q).Type
					found = true
				}
				if found {
					if i < 1 {
						return nil, nil, errors.New("bare vlan")
					}
					base := data.layers[i-1]
					if base.LayerType() == layers.LayerTypeEthernet {
						base.(*layers.Ethernet).EthernetType = ethertype
					} else {
						return nil, nil, errors.New("unsupported")
					}
					continue
				}
			}
			buf = append(buf, layer)
		}
		if found {
			data.layers = buf
		} else {
			return nil, nil, errors.New("pop vlan failed")
		}
	case ofp4.OFPAT_DEC_NW_TTL:
		func() { // for direct exit from switch
			for _, layer := range data.Layers() {
				switch clayer := layer.(type) {
				case *layers.IPv4:
					if clayer.TTL > 1 {
						clayer.TTL--
					} else {
						// packet_in ?
					}
					return
				case *layers.IPv6:
					if clayer.HopLimit > 1 {
						clayer.HopLimit--
					} else {
						// packet_in ?
					}
					return
				}
			}
		}()
	case ofp4.OFPAT_POP_PBB:
		var buf []gopacket.Layer
		found := false
		for i, layer := range data.Layers() {
			if found == false {
				switch pbb := layer.(type) {
				case *layers2.PBB:
					found = true
					if i < 1 {
						panic("bare pbb")
					} else if eth, ok := data.layers[i-1].(*layers.Ethernet); ok {
						eth.EthernetType = pbb.Type
						eth.SrcMAC = pbb.SrcMAC
						eth.DstMAC = pbb.DstMAC
					} else {
						panic("Unsupported")
					}
					continue
				}
			}
			buf = append(buf, layer)
		}
		if found {
			data.layers = buf
		} else {
			return nil, nil, errors.New("pop vlan failed")
		}
	}
	return nil, nil, nil
}
Beispiel #21
0
func (self *actionList) UnmarshalBinary(data []byte) error {
	var actions []action
	for _, msg := range ofp4.ActionHeader(data).Iter() {
		var act action
		switch msg.Type() {
		default:
			return errors.New("unknown ofp4.Action type")
		case ofp4.OFPAT_COPY_TTL_OUT,
			ofp4.OFPAT_COPY_TTL_IN,
			ofp4.OFPAT_DEC_MPLS_TTL,
			ofp4.OFPAT_POP_VLAN,
			ofp4.OFPAT_DEC_NW_TTL,
			ofp4.OFPAT_POP_PBB:
			act = actionGeneric{
				Type: msg.Type(),
			}
		case ofp4.OFPAT_OUTPUT:
			a := ofp4.ActionOutput(msg)
			act = actionOutput{
				Port:   a.Port(),
				MaxLen: a.MaxLen(),
			}
		case ofp4.OFPAT_SET_MPLS_TTL:
			act = actionMplsTtl{
				MplsTtl: ofp4.ActionMplsTtl(msg).MplsTtl(),
			}
		case ofp4.OFPAT_PUSH_VLAN,
			ofp4.OFPAT_PUSH_MPLS,
			ofp4.OFPAT_PUSH_PBB:
			act = actionPush{
				Type:      msg.Type(),
				Ethertype: ofp4.ActionPush(msg).Ethertype(),
			}
		case ofp4.OFPAT_POP_MPLS:
			act = actionPopMpls{
				Ethertype: ofp4.ActionPopMpls(msg).Ethertype(),
			}
		case ofp4.OFPAT_SET_QUEUE:
			act = actionSetQueue{
				QueueId: ofp4.ActionSetQueue(msg).QueueId(),
			}
		case ofp4.OFPAT_GROUP:
			act = actionGroup{
				GroupId: ofp4.ActionGroup(msg).GroupId(),
			}
		case ofp4.OFPAT_SET_NW_TTL:
			act = actionNwTtl{
				NwTtl: ofp4.ActionNwTtl(msg).NwTtl(),
			}
		case ofp4.OFPAT_SET_FIELD:
			f := ofp4.ActionSetField(msg).Field()
			act = actionSetField{
				Field: f[:f.Header().Length()+4],
			}
		case ofp4.OFPAT_EXPERIMENTER:
			a := ofp4.ActionExperimenterHeader(msg)
			if handler, ok := actionHandlers[a.Experimenter()]; ok {
				act = actionExperimenter{
					Experimenter: a.Experimenter(),
					Data:         msg[8:],
					Handler:      handler,
				}
			} else {
				return ofp4.MakeErrorMsg(
					ofp4.OFPET_BAD_ACTION,
					ofp4.OFPBAC_BAD_EXPERIMENTER,
				)
			}
		}
		actions = append(actions, act)
	}
	*self = actions
	return nil
}
Beispiel #22
0
func (self *ofmMeterMod) Map() Reducable {
	pipe := self.pipe

	req := ofp4.MeterMod(self.req)
	switch req.Command() {
	case ofp4.OFPMC_ADD:
		meterId := req.MeterId()
		if meterId == 0 || (meterId > ofp4.OFPM_MAX && meterId != ofp4.OFPM_CONTROLLER) {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_METER_MOD_FAILED, ofp4.OFPMMFC_INVALID_METER))
		} else {
			var bands bandList
			if err := bands.UnmarshalBinary(req.Bands()); err != nil {
				log.Print(err)
			}

			var highestBand band
			for _, b := range bands {
				if highestBand == nil || highestBand.getRate() < b.getRate() {
					highestBand = b
				}
			}
			newMeter := &meter{
				lock:        &sync.Mutex{},
				created:     time.Now(),
				bands:       bands,
				highestBand: highestBand,
			}
			if req.Flags()&ofp4.OFPMF_PKTPS != 0 {
				newMeter.flagPkts = true
			}
			if req.Flags()&ofp4.OFPMF_BURST != 0 {
				newMeter.flagBurst = true
			}
			if req.Flags()&ofp4.OFPMF_STATS != 0 {
				newMeter.flagStats = true
			}

			if err := func() error {
				pipe.lock.Lock()
				defer pipe.lock.Unlock()

				if _, exists := pipe.meters[meterId]; exists {
					return ofp4.MakeErrorMsg(
						ofp4.OFPET_METER_MOD_FAILED,
						ofp4.OFPMMFC_METER_EXISTS,
					)
				} else {
					pipe.meters[meterId] = newMeter
				}
				return nil
			}(); err != nil {
				if e, ok := err.(ofp4.ErrorMsg); ok {
					self.putError(e)
				} else {
					log.Print(err)
				}
			}
		}
	case ofp4.OFPMC_DELETE:
		meterId := req.MeterId()
		if err := func() error {
			pipe.lock.Lock()
			defer pipe.lock.Unlock()

			if meterId == ofp4.OFPM_ALL {
				for meterId, _ := range pipe.meters {
					pipe.deleteMeterInside(meterId)
				}
			} else {
				return pipe.deleteMeterInside(meterId)
			}
			return nil
		}(); err != nil {
			if e, ok := err.(ofp4.ErrorMsg); ok {
				self.putError(e)
			} else {
				log.Print(err)
			}
		}
	case ofp4.OFPMC_MODIFY:
		// XXX:
	}
	return self
}
Beispiel #23
0
func (self actionPush) Process(data *Frame) (*outputToPort, *outputToGroup, error) {
	var buf []gopacket.Layer
	found := false
	switch self.Type {
	case ofp4.OFPAT_PUSH_VLAN:
		for i, layer := range data.Layers() {
			buf = append(buf, layer)

			if found == false {
				switch layer.LayerType() {
				case layers.LayerTypeEthernet:
					eth := layer.(*layers.Ethernet)
					ethertype := eth.EthernetType
					eth.EthernetType = layers.EthernetType(self.Ethertype)

					dot1q := &layers.Dot1Q{Type: ethertype}
					if d, ok := data.layers[i+1].(*layers.Dot1Q); ok {
						dot1q.Priority = d.Priority
						dot1q.DropEligible = d.DropEligible
						dot1q.VLANIdentifier = d.VLANIdentifier
					}
					buf = append(buf, dot1q)
					found = true
				}
			}
		}
	case ofp4.OFPAT_PUSH_MPLS:
		for i, layer := range data.Layers() {
			if found == false {
				var ttl uint8
				var base gopacket.Layer
				var mpls *layers.MPLS

				switch t := layer.(type) {
				case *layers.MPLS:
					base = data.layers[i-1]
					ttl = t.TTL
					mpls = t
				case *layers.IPv4:
					base = data.layers[i-1]
					ttl = t.TTL
				case *layers.IPv6:
					base = data.layers[i-1]
					ttl = t.HopLimit
				case *layers.ARP:
					base = data.layers[i-1]
				}
				if base != nil {
					if base.LayerType() == layers.LayerTypeEthernet {
						base.(*layers.Ethernet).EthernetType = layers.EthernetType(self.Ethertype)
					} else if base.LayerType() == layers.LayerTypeDot1Q {
						base.(*layers.Dot1Q).Type = layers.EthernetType(self.Ethertype)
					} else {
						return nil, nil, errors.New("unsupported")
					}
					if mpls != nil {
						buf = append(buf, &layers.MPLS{
							Label:        mpls.Label,
							TrafficClass: mpls.TrafficClass,
							StackBottom:  false,
							TTL:          ttl,
						})
					} else {
						buf = append(buf, &layers.MPLS{
							StackBottom: true,
							TTL:         ttl,
						})
					}
					found = true
				}
			}
			buf = append(buf, layer)
		}
	case ofp4.OFPAT_PUSH_PBB:
		for _, layer := range data.Layers() {
			buf = append(buf, layer)
			if found == false {
				switch layer.LayerType() {
				case layers.LayerTypeEthernet:
					eth := layer.(*layers.Ethernet)
					ethertype := eth.EthernetType
					eth.EthernetType = layers.EthernetType(self.Ethertype)
					buf = append(buf, &layers2.PBB{
						DstMAC: eth.DstMAC,
						SrcMAC: eth.SrcMAC,
						Type:   ethertype,
					})
					found = true
				}
			}
		}
	default:
		return nil, nil, ofp4.MakeErrorMsg(
			ofp4.OFPET_BAD_ACTION,
			ofp4.OFPBAC_BAD_TYPE,
		)
	}
	if found {
		data.layers = buf
	} else {
		return nil, nil, errors.New("push vlan failed")
	}
	return nil, nil, nil
}