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 } }
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 } }
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") } }
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 }
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 }