예제 #1
0
파일: match.go 프로젝트: hkwi/gopenflow
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
}
예제 #2
0
파일: match_nxm.go 프로젝트: hkwi/gopenflow
func (self oxmNxm) Parse(buf []byte) map[OxmKey]OxmPayload {
	ret := make(map[OxmKey]OxmPayload)
	for _, oxm := range ofp4.Oxm(buf).Iter() {
		hdr := oxm.Header()
		length := hdr.Length()
		if hdr.HasMask() {
			length = length / 2
		}
		switch hdr.Class() {
		case ofp4.OFPXMC_NXM_0, ofp4.OFPXMC_NXM_1:
			ret[OxmKeyBasic(hdr.Type())] = OxmValueMask{
				Value: oxm[4 : 4+length],
				Mask:  oxm[4+length:],
			}
		}
	}
	return ret
}
예제 #3
0
파일: match.go 프로젝트: hkwi/gopenflow
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
}
예제 #4
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
}