Example #1
0
func (self StratosOxm) Conflict(key ofp4sw.OxmKey, a, b ofp4sw.OxmPayload) (bool, error) {
	if useOxmMultiValue(key) {
		// does not conflict by syntax
		return false, nil
	} else {
		x := a.(ofp4sw.OxmValueMask)
		y := b.(ofp4sw.OxmValueMask)

		if skey, ok := key.(OxmKeyStratos); ok && skey.Type == oxm.STROXM_BASIC_DOT11 && skey.Field == oxm.STRATOS_OXM_FIELD_BASIC {
			var xval, yval uint8
			if len(x.Value) > 0 {
				xval = x.Value[0]
			}
			if len(y.Value) > 0 {
				yval = y.Value[0]
			}
			switch {
			case xval == 1 && yval == 2:
				return true, nil
			case xval == 2 && yval == 1:
				return true, nil
			default:
				return false, nil
			}
		}

		mask := bytes2.And(x.Mask, y.Mask)
		return bytes.Equal(bytes2.And(x.Value, mask), bytes2.And(y.Value, mask)), nil
	}
}
Example #2
0
func (self StratosOxm) Fit(key ofp4sw.OxmKey, narrow, wide ofp4sw.OxmPayload) (bool, error) {
	if useOxmMultiValue(key) {
		n := narrow.(OxmMultiValue)
		w := wide.(OxmMultiValue)
		for _, wv := range w.Values {
			if missing := func() bool {
				for _, nv := range n.Values {
					if bytes.HasPrefix(nv, wv) {
						return false
					}
				}
				return true
			}(); missing {
				return false, nil
			}
		}
		return true, nil
	} else {
		n := narrow.(ofp4sw.OxmValueMask)
		w := wide.(ofp4sw.OxmValueMask)

		if skey, ok := key.(OxmKeyStratos); ok && skey.Type == oxm.STROXM_BASIC_DOT11 && skey.Field == oxm.STRATOS_OXM_FIELD_BASIC {
			var nval, wval uint8
			if len(n.Value) > 0 {
				nval = n.Value[0]
			}
			if len(w.Value) > 0 {
				wval = w.Value[0]
			}
			switch wval {
			default:
				return true, nil
			case 1:
				return nval == 1, nil
			case 2:
				return nval != 1, nil
			}
		}

		mask := make([]byte, len(w.Value))
		for i, _ := range mask {
			mask[i] = 0xFF
		}
		if len(w.Mask) > 0 {
			mask = bytes2.And(mask, w.Mask)
		}
		if len(n.Mask) > 0 {
			mask = bytes2.And(mask, n.Mask)
		}
		return bytes.Equal(bytes2.And(n.Value, mask), w.Value), nil
	}
}
Example #3
0
func (self *OxmValueMask) Merge(vm OxmValueMask) error {
	mask := bytes2.And(self.Mask, vm.Mask)
	if bytes.Equal(bytes2.And(self.Value, mask), bytes2.And(vm.Value, mask)) {
		value := func(o OxmValueMask) []byte {
			if len(o.Mask) > 0 {
				return bytes2.And(o.Value, o.Mask)
			} else {
				return o.Value
			}
		}
		self.Value = bytes2.Or(value(*self), value(vm))
		self.Mask = bytes2.Or(self.Mask, vm.Mask)
		return nil
	} else {
		return fmt.Errorf("conflict")
	}
}
Example #4
0
func (self StratosOxm) Match(data ofp4sw.Frame, key ofp4sw.OxmKey, payload ofp4sw.OxmPayload) (bool, error) {
	switch k := key.(type) {
	case OxmKeyStratos:
		switch k.Field {
		case oxm.STRATOS_OXM_FIELD_BASIC:
			fetch11 := func() *layers.Dot11 {
				for _, layer := range data.Layers() {
					switch l := layer.(type) {
					case *layers.Dot11:
						return l
					}
				}
				return nil
			}

			fetchIeList := func() (ret []*layers.Dot11InformationElement) {
				for _, layer := range data.Layers() {
					switch l := layer.(type) {
					case *layers.Dot11InformationElement:
						ret = append(ret, l)
					}
				}
				return
			}

			switch k.Type {
			case oxm.STROXM_BASIC_DOT11:
				p := payload.(ofp4sw.OxmValueMask)
				var want uint8
				if len(p.Value) > 0 {
					want = p.Value[0]
				}
				var have uint8
				if val, ok := data.Oob[key]; ok && val != nil {
					if v, ok := val.(ofp4sw.OxmValueMask); ok && len(v.Value) > 0 {
						have = v.Value[0]
					}
				}
				switch want {
				case 1:
					return have == 1, nil
				case 2:
					return have != 1, nil
				default:
					return true, nil
				}
			case oxm.STROXM_BASIC_DOT11_FRAME_CTRL:
				if m := fetch11(); m != nil {
					p := payload.(ofp4sw.OxmValueMask)
					v := []byte{
						uint8(m.Type<<2) | m.Proto,
						uint8(m.Flags),
					}
					if len(p.Mask) > 0 {
						return bytes.Equal(p.Value, bytes2.And(v, p.Mask)), nil
					} else {
						return bytes.Equal(p.Value, v), nil
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR1:
				if m := fetch11(); m != nil {
					p := payload.(ofp4sw.OxmValueMask)
					if len(p.Mask) > 0 {
						return bytes.Equal(p.Value, bytes2.And([]byte(m.Address1), p.Mask)), nil
					} else {
						return bytes.Equal(p.Value, []byte(m.Address1)), nil
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR2:
				if m := fetch11(); m != nil {
					p := payload.(ofp4sw.OxmValueMask)
					if len(p.Mask) > 0 {
						return bytes.Equal(p.Value, bytes2.And([]byte(m.Address2), p.Mask)), nil
					} else {
						return bytes.Equal(p.Value, []byte(m.Address2)), nil
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR3:
				if m := fetch11(); m != nil {
					p := payload.(ofp4sw.OxmValueMask)
					if len(p.Mask) > 0 {
						return bytes.Equal(p.Value, bytes2.And([]byte(m.Address3), p.Mask)), nil
					} else {
						return bytes.Equal(p.Value, []byte(m.Address3)), nil
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR4:
				if m := fetch11(); m != nil {
					p := payload.(ofp4sw.OxmValueMask)
					if len(p.Mask) > 0 {
						return bytes.Equal(p.Value, bytes2.And([]byte(m.Address4), p.Mask)), nil
					} else {
						return bytes.Equal(p.Value, []byte(m.Address4)), nil
					}
				}
			case oxm.STROXM_BASIC_DOT11_SSID:
				for _, l := range fetchIeList() {
					if l.ID == 0 {
						p := payload.(ofp4sw.OxmValueMask)
						if len(p.Mask) > 0 {
							return bytes.Equal(p.Value, bytes2.And(l.Info, p.Mask)), nil
						} else {
							return bytes.Equal(p.Value, l.Info), nil
						}
					}
				}
				return false, nil
			case oxm.STROXM_BASIC_DOT11_ACTION_CATEGORY:
				// XXX: HT field handling is missing in gopacket
				if m := fetch11(); m != nil && m.Type.MainType() == layers.Dot11TypeMgmt {
					p := payload.(ofp4sw.OxmValueMask)
					return bytes.HasPrefix(m.Payload, p.Value), nil
				}
			case oxm.STROXM_BASIC_DOT11_PUBLIC_ACTION:
				if m := fetch11(); m != nil && m.Type.MainType() == layers.Dot11TypeMgmt && m.Payload[0] == 4 { // Public Action
					p := payload.(ofp4sw.OxmValueMask)
					v := m.Payload[1] // Public Action field value
					if len(p.Mask) > 0 {
						v &= p.Mask[0]
					}
					return v == p.Value[0], nil
				}
			case oxm.STROXM_BASIC_DOT11_TAG:
				ies := fetchIeList()
				for _, v := range payload.(OxmMultiValue).Values {
					for _, ie := range ies {
						if v[0] == uint8(ie.ID) {
							return true, nil
						}
					}
				}
				return false, nil
			case oxm.STROXM_BASIC_DOT11_TAG_VENDOR:
				ies := fetchIeList()
				for _, v := range payload.(OxmMultiValue).Values {
					for _, ie := range ies {
						if ie.ID == 221 && bytes.HasPrefix(ie.OUI, v) {
							return true, nil
						}
					}
				}
				return false, nil
			default:
				return false, fmt.Errorf("unsupported oxm experimenter type")
			}
		case oxm.STRATOS_OXM_FIELD_RADIOTAP:
			p := payload.(ofp4sw.OxmValueMask)

			if val, ok := data.Oob[key]; ok && val != nil {
				if v, ok := val.(ofp4sw.OxmValueMask); ok && len(v.Value) > 0 {
					if len(p.Mask) > 0 {
						return bytes.Equal(p.Value, bytes2.And(v.Value, p.Mask)), nil
					} else {
						return bytes.Equal(p.Value, v.Value), nil
					}
				}
			}
		default:
			return false, fmt.Errorf("unsupported oxm experimenter field")
		}
	default:
		return false, fmt.Errorf("unknown oxm key")
	}
	return false, nil
}
Example #5
0
func (self StratosOxm) SetField(data *ofp4sw.Frame, key ofp4sw.OxmKey, payload ofp4sw.OxmPayload) error {
	switch k := key.(type) {
	case OxmKeyStratos:
		switch k.Field {
		case oxm.STRATOS_OXM_FIELD_BASIC:
			p := payload.(ofp4sw.OxmValueMask)

			fetch11 := func() *layers.Dot11 {
				for _, layer := range data.Layers() {
					switch l := layer.(type) {
					case *layers.Dot11:
						return l
					}
				}
				return nil
			}

			fetchIeList := func() (ret []*layers.Dot11InformationElement) {
				for _, layer := range data.Layers() {
					switch l := layer.(type) {
					case *layers.Dot11InformationElement:
						ret = append(ret, l)
					}
				}
				return
			}

			switch k.Type {
			case oxm.STROXM_BASIC_DOT11:
				data.Oob[key] = ofp4sw.OxmValueMask{
					Value: p.Value,
				}
			case oxm.STROXM_BASIC_DOT11_FRAME_CTRL:
				if m := fetch11(); m != nil {
					v := []byte{
						uint8(m.Type<<2) | m.Proto,
						uint8(m.Flags),
					}
					v = bytes2.Or(p.Value, bytes2.And(v, p.Mask))
					m.Proto = v[0] & 0x03
					m.Type = layers.Dot11Type(v[0] >> 2)
					m.Flags = layers.Dot11Flags(v[1])
				}
			case oxm.STROXM_BASIC_DOT11_ADDR1:
				if m := fetch11(); m != nil {
					if len(p.Mask) > 0 {
						m.Address1 = bytes2.Or(p.Value, bytes2.And([]byte(m.Address1), p.Mask))
					} else {
						m.Address1 = p.Value
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR2:
				if m := fetch11(); m != nil {
					if len(p.Mask) > 0 {
						m.Address2 = bytes2.Or(p.Value, bytes2.And([]byte(m.Address2), p.Mask))
					} else {
						m.Address2 = p.Value
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR3:
				if m := fetch11(); m != nil {
					if len(p.Mask) > 0 {
						m.Address3 = bytes2.Or(p.Value, bytes2.And([]byte(m.Address3), p.Mask))
					} else {
						m.Address3 = p.Value
					}
				}
			case oxm.STROXM_BASIC_DOT11_ADDR4:
				if m := fetch11(); m != nil {
					if len(p.Mask) > 0 {
						m.Address4 = bytes2.Or(p.Value, bytes2.And([]byte(m.Address4), p.Mask))
					} else {
						m.Address4 = p.Value
					}
				}
			case oxm.STROXM_BASIC_DOT11_SSID:
				for _, l := range fetchIeList() {
					if l.ID == 0 {
						if len(p.Mask) > 0 {
							l.Info = bytes2.Or(p.Value, bytes2.And(l.Info, p.Mask))
						} else {
							l.Info = p.Value
						}
					}
				}
			default:
				return fmt.Errorf("unsupported oxm experimenter type")
			}
		case oxm.STRATOS_OXM_FIELD_RADIOTAP:
			p := payload.(ofp4sw.OxmValueMask)

			if v, ok := data.Oob[key].(ofp4sw.OxmValueMask); !ok {
				data.Oob[key] = payload
			} else if len(p.Mask) > 0 {
				v.Value = bytes2.Or(p.Value, bytes2.And(v.Value, p.Mask))
				data.Oob[key] = v
			} else {
				data.Oob[key] = ofp4sw.OxmValueMask{
					Value: p.Value,
				}
			}
		default:
			return fmt.Errorf("unsupported oxm experimenter field")
		}
	default:
		return fmt.Errorf("unknown oxm key")
	}
	return nil
}