Exemplo n.º 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
}
Exemplo n.º 2
0
func (self StratosOxm) Parse(buf []byte) map[ofp4sw.OxmKey]ofp4sw.OxmPayload {
	ret := make(map[ofp4sw.OxmKey]ofp4sw.OxmPayload)
	for _, oxmbuf := range oxm.Oxm(buf).Iter() {
		hdr := oxmbuf.Header()
		if hdr.Class() == ofp4.OFPXMC_EXPERIMENTER {
			exp := ofp4.OxmExperimenterHeader(oxmbuf)
			if exp.Experimenter() == oxm.STRATOS_EXPERIMENTER_ID {
				key := OxmKeyStratos(hdr.Field())
				length := hdr.Length() - 4
				if useOxmMultiValue(key) {
					payload := OxmMultiValue{}
					if p, ok := ret[key]; ok {
						payload = p.(OxmMultiValue)
					}
					payload.Values = append(payload.Values, oxmbuf[8:8+length])
					ret[key] = payload
				} else {
					if hdr.HasMask() {
						ret[key] = ofp4sw.OxmValueMask{
							Value: oxmbuf[8 : 8+length/2],
							Mask:  oxmbuf[8+length/2:],
						}
					} else {
						ret[key] = ofp4sw.OxmValueMask{
							Value: oxmbuf[8 : 8+length],
						}
					}
				}
			}
		}
	}
	return ret
}
Exemplo n.º 3
0
func hookDot11Action(hdr oxm.Oxm) (uint32, []byte) {
	var inPort uint32
	for _, o := range hdr.Iter() {
		if o.Header().Type() == oxm.OXM_OF_IN_PORT {
			inPort = binary.BigEndian.Uint32(o[4:])
		}
	}
	var action []byte
	for _, o := range hdr.Iter() {
		if o.Header().Class() != ofp4.OFPXMC_EXPERIMENTER {
			continue
		}
		if ofp4.OxmExperimenterHeader(o).Experimenter() != oxm.STRATOS_EXPERIMENTER_ID {
			continue
		}
		switch o.Header().Field() {
		case oxm.STROXM_BASIC_DOT11_ACTION_CATEGORY:
			buf := o[8:]
			if len(action) < len(buf) {
				action = buf
			}
		case oxm.STROXM_BASIC_DOT11_PUBLIC_ACTION:
			buf := append([]byte{4}, o[8:]...)
			if len(action) < len(buf) {
				action = buf
			}
		}
	}
	return inPort, action
}
Exemplo n.º 4
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
}
Exemplo n.º 5
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
}
Exemplo n.º 6
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
}