예제 #1
0
func (self OxmKeyExp) Bytes(payload OxmPayload) []byte {
	hdr := oxm.Header(oxm.OFPXMC_EXPERIMENTER<<oxm.OXM_CLASS_SHIFT | uint32(self.Field)<<oxm.OXM_FIELD_SHIFT)
	var buf []byte
	setCommon := func(payloadLength int) {
		buf = make([]byte, 4+payloadLength)
		hdr.SetLength(payloadLength)
		binary.BigEndian.PutUint32(buf, uint32(hdr))
		binary.BigEndian.PutUint32(buf[4:], self.Experimenter)
		binary.BigEndian.PutUint16(buf[8:], self.Type)
	}
	switch p := payload.(type) {
	case OxmValueMask:
		if len(p.Mask) > 0 {
			hdr.SetMask(true)
		}
		setCommon(6 + len(p.Value) + len(p.Mask))
		copy(buf[10:], p.Value)
		copy(buf[10+len(p.Value):], p.Mask)
	case []byte:
		setCommon(6 + len(p))
		copy(buf[10:], p)
	case nil:
		setCommon(6)
	}
	return buf
}
예제 #2
0
func (self OxmKeyStratos) Bytes(payload ofp4sw.OxmPayload) []byte {
	hdr := oxm.Header(oxm.OFPXMC_EXPERIMENTER<<oxm.OXM_CLASS_SHIFT | uint32(self.Field)<<oxm.OXM_FIELD_SHIFT)
	makeCommon := func(payloadLength int) []byte {
		buf := make([]byte, 10+payloadLength)
		hdr.SetLength(6 + payloadLength)
		binary.BigEndian.PutUint32(buf, uint32(hdr))
		binary.BigEndian.PutUint32(buf[4:], uint32(oxm.STRATOS_EXPERIMENTER_ID))
		binary.BigEndian.PutUint16(buf[8:], self.Type)
		return buf
	}
	switch p := payload.(type) {
	case ofp4sw.OxmValueMask:
		if len(p.Mask) > 0 {
			hdr.SetMask(true)
		}
		buf := makeCommon(len(p.Value) + len(p.Mask))
		copy(buf[10:], p.Value)
		copy(buf[10+len(p.Value):], p.Mask)
		return buf
	case OxmMultiValue:
		var ret []byte
		for _, v := range p.Values {
			buf := makeCommon(len(v))
			copy(buf[10:], v)
			ret = append(ret, buf...)
		}
		return ret
	}
	return nil
}
예제 #3
0
파일: match.go 프로젝트: hkwi/gopenflow
func (self matchHash) Key(target matchHash) uint32 {
	hasher := fnv.New32()
	for k, s := range self {
		var value, mask []byte
		if bKey, ok := k.(OxmKeyBasic); !ok || oxm.Header(bKey).Class() != ofp4.OFPXMC_OPENFLOW_BASIC {
			continue
		} else {
			length, _ := ofp4.OxmOfDefs(uint32(bKey))
			value = make([]byte, length)
			mask = make([]byte, length)
		}
		if t, ok := target[k]; ok {
			a := s.(OxmValueMask)
			b := t.(OxmValueMask)
			for i, _ := range mask {
				mask[i] = 0xFF
			}
			if a.Mask != nil {
				for i, _ := range mask {
					mask[i] &= a.Mask[i]
				}
			}
			if b.Mask != nil {
				for i, _ := range mask {
					mask[i] &= b.Mask[i]
				}
			}
			for i, _ := range value {
				value[i] = b.Value[i] & mask[i]
			}
		}
		hasher.Write(value)
	}
	return hasher.Sum32()
}
예제 #4
0
파일: match.go 프로젝트: hkwi/gopenflow
func (self match) Match(data Frame) bool {
	for oxmKey, oxmPayload := range self {
		var handler OxmHandler
		switch k := oxmKey.(type) {
		case OxmKeyBasic:
			switch oxm.Header(k).Class() {
			case ofp4.OFPXMC_OPENFLOW_BASIC:
				handler = oxmBasicHandler
			case ofp4.OFPXMC_NXM_0, OFPXMC_NXM_1:
				handler = oxmNxmHandler
			}
		default:
			handler = oxmHandlers[oxmKeys[oxmKey]]
		}
		if handler == nil {
			log.Printf("oxm handler not found for %v", oxmKey)
			return false
		}
		if result, err := handler.Match(data, oxmKey, oxmPayload); err != nil {
			log.Print(err)
			return false
		} else if !result {
			return false
		}
	}
	return true
}
예제 #5
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
}
예제 #6
0
파일: match_nxm.go 프로젝트: hkwi/gopenflow
func (self oxmNxm) OxmId(id uint32) uint32 {
	length, mask := nxmDefs(id)
	hdr := oxm.Header(id)
	hdr.SetMask(mask)
	if mask {
		hdr.SetLength(length * 2)
	} else {
		hdr.SetLength(length)
	}
	return uint32(hdr)
}
예제 #7
0
파일: match.go 프로젝트: hkwi/gopenflow
// creates a common match union parameter.
func (self matchHash) Merge(from matchHash) {
	var removal []OxmKey
	for k, s := range self {
		var a, b OxmValueMask
		var length int
		if bKey, ok := k.(OxmKeyBasic); !ok || oxm.Header(bKey).Class() != ofp4.OFPXMC_OPENFLOW_BASIC {
			continue
		} else if f, ok := from[k]; !ok {
			removal = append(removal, k)
			continue
		} else {
			a = s.(OxmValueMask)
			b = f.(OxmValueMask)
			length, _ = ofp4.OxmOfDefs(uint32(bKey))
		}
		fullMask := true
		mask := make([]byte, length)
		for i, _ := range mask {
			mask[i] = 0xFF
		}
		if a.Mask != nil {
			for i, _ := range mask {
				mask[i] &= a.Mask[i]
			}
		}
		if b.Mask != nil {
			for i, _ := range mask {
				mask[i] &= b.Mask[i]
			}
		}
		for i, m := range mask {
			mask[i] &^= (a.Value[i] & m) ^ (b.Value[i] & m)
			if mask[i] != 0 {
				fullMask = false
			}
		}
		if fullMask {
			removal = append(removal, k)
			continue
		}
		payload := OxmValueMask{
			Value: make([]byte, length),
			Mask:  mask,
		}
		for i, m := range mask {
			payload.Value[i] = a.Value[i] & m
		}
		self[k] = payload
	}
	for _, rem := range removal {
		delete(self, rem)
	}
}
예제 #8
0
파일: util.go 프로젝트: hkwi/gopenflow
func makeOxmBasic(oxmType uint32) []byte {
	length, mask := ofp4.OxmOfDefs(oxmType)
	if mask {
		length = length * 2
	}
	hdr := oxm.Header(oxmType)
	hdr.SetMask(mask)
	hdr.SetLength(length)
	buf := make([]byte, 4+length)
	binary.BigEndian.PutUint32(buf, oxmType)
	return buf
}
예제 #9
0
func (self OxmKeyBasic) Bytes(payload OxmPayload) []byte {
	vm := payload.(OxmValueMask)
	buf := make([]byte, 4+len(vm.Value)+len(vm.Mask))

	hdr := oxm.Header(self)
	if len(vm.Mask) > 0 {
		hdr.SetMask(true)
	}
	hdr.SetLength(len(buf) - 4)
	binary.BigEndian.PutUint32(buf, uint32(hdr))

	copy(buf[4:], vm.Value)
	copy(buf[4+len(vm.Value):], vm.Mask)
	return buf
}
예제 #10
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
}
예제 #11
0
파일: ext.go 프로젝트: hkwi/gopenflow
func (self OxmKeyExp) Bytes(payload OxmPayload) []byte {
	hdr := oxm.Header(oxm.OFPXMC_EXPERIMENTER<<oxm.OXM_CLASS_SHIFT | uint32(self.Field)<<oxm.OXM_FIELD_SHIFT)
	var value, mask []byte
	switch p := payload.(type) {
	case OxmValueMask:
		value = p.Value
		mask = p.Mask
	case []byte:
		value = p
	}
	if len(mask) > 0 {
		hdr.SetMask(true)
	}
	buf = make([]byte, 8+len(value)+len(mask))
	hdr.SetLength(4 + len(value) + len(mask))
	binary.BigEndian.PutUint32(buf, uint32(hdr))
	binary.BigEndian.PutUint32(buf[4:], self.Experimenter)
	copy(buf[8:], value)
	copy(buf[8+len(value):], mask)
	return buf
}
예제 #12
0
파일: match.go 프로젝트: hkwi/gopenflow
/*
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
}
예제 #13
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
}
예제 #14
0
파일: enum.go 프로젝트: hkwi/gopenflow
func OxmOfDefs(hdr uint32) (length int, mayMask bool) {
	switch oxm.Header(hdr).Type() {
	default:
		return 0, false
	case oxm.OXM_OF_IN_PORT:
		return 4, false
	case oxm.OXM_OF_IN_PHY_PORT:
		return 4, false
	case oxm.OXM_OF_METADATA:
		return 8, true
	case oxm.OXM_OF_ETH_DST:
		return 6, true
	case oxm.OXM_OF_ETH_SRC:
		return 6, true
	case oxm.OXM_OF_ETH_TYPE:
		return 2, false
	case oxm.OXM_OF_VLAN_VID:
		return 2, true
	case oxm.OXM_OF_VLAN_PCP:
		return 1, false
	case oxm.OXM_OF_IP_DSCP:
		return 1, false
	case oxm.OXM_OF_IP_ECN:
		return 1, false
	case oxm.OXM_OF_IP_PROTO:
		return 1, false
	case oxm.OXM_OF_IPV4_SRC:
		return 4, true
	case oxm.OXM_OF_IPV4_DST:
		return 4, true
	case oxm.OXM_OF_TCP_SRC:
		return 2, false
	case oxm.OXM_OF_TCP_DST:
		return 2, false
	case oxm.OXM_OF_UDP_SRC:
		return 2, false
	case oxm.OXM_OF_UDP_DST:
		return 2, false
	case oxm.OXM_OF_SCTP_SRC:
		return 2, false
	case oxm.OXM_OF_SCTP_DST:
		return 2, false
	case oxm.OXM_OF_ICMPV4_TYPE:
		return 1, false
	case oxm.OXM_OF_ICMPV4_CODE:
		return 1, false
	case oxm.OXM_OF_ARP_OP:
		return 2, false
	case oxm.OXM_OF_ARP_SPA:
		return 4, true
	case oxm.OXM_OF_ARP_TPA:
		return 4, true
	case oxm.OXM_OF_ARP_SHA:
		return 6, true
	case oxm.OXM_OF_ARP_THA:
		return 6, true
	case oxm.OXM_OF_IPV6_SRC:
		return 16, true
	case oxm.OXM_OF_IPV6_DST:
		return 16, true
	case oxm.OXM_OF_IPV6_FLABEL:
		return 4, true
	case oxm.OXM_OF_ICMPV6_TYPE:
		return 1, false
	case oxm.OXM_OF_ICMPV6_CODE:
		return 1, false
	case oxm.OXM_OF_IPV6_ND_TARGET:
		return 16, false
	case oxm.OXM_OF_IPV6_ND_SLL:
		return 6, false
	case oxm.OXM_OF_IPV6_ND_TLL:
		return 6, false
	case oxm.OXM_OF_MPLS_LABEL:
		return 4, true
	case oxm.OXM_OF_MPLS_TC:
		return 1, false
	case oxm.OXM_OF_MPLS_BOS:
		return 1, false
	case oxm.OXM_OF_PBB_ISID:
		return 3, true
	case oxm.OXM_OF_TUNNEL_ID:
		return 8, true
	case oxm.OXM_OF_IPV6_EXTHDR:
		return 2, true
	}
}
예제 #15
0
파일: conv_oxm.go 프로젝트: hkwi/gopenflow
func (self Oxm) Header() oxm.Header {
	return oxm.Header(binary.BigEndian.Uint32(self))
}
예제 #16
0
파일: frame.go 프로젝트: hkwi/gopenflow
func (self *Frame) getValue(oxmType uint32) ([]byte, error) {
	switch oxm.Header(oxmType).Type() {
	default:
		return nil, fmt.Errorf("unknown oxm field %x", oxmType)
	case oxm.OXM_OF_IN_PORT:
		return toMatchBytes(self.inPort)
	case oxm.OXM_OF_IN_PHY_PORT:
		return toMatchBytes(self.inPhyPort)
	case oxm.OXM_OF_METADATA:
		return toMatchBytes(self.metadata)
	case oxm.OXM_OF_ETH_DST:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.Ethernet); ok {
				return toMatchBytes(t.DstMAC)
			}
		}
	case oxm.OXM_OF_ETH_SRC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.Ethernet); ok {
				return toMatchBytes(t.SrcMAC)
			}
		}
	case oxm.OXM_OF_ETH_TYPE:
		do_break := false
		var ret []byte
		for _, layer := range self.Layers() {
			switch t := layer.(type) {
			case *layers.Ethernet:
				if buf, err := toMatchBytes(t.EthernetType); err != nil {
					return nil, err
				} else {
					ret = buf
				}
			case *layers.Dot1Q:
				if buf, err := toMatchBytes(t.Type); err != nil {
					return nil, err
				} else {
					ret = buf
				}
			default:
				do_break = true
			}
			if do_break {
				break
			}
		}
		if ret != nil {
			return ret, nil
		}
	case oxm.OXM_OF_VLAN_VID:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.Dot1Q); ok {
				return toMatchBytes(t.VLANIdentifier | 0x1000)
			}
		}
		return toMatchBytes(uint16(0x0000))
	case oxm.OXM_OF_VLAN_PCP:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.Dot1Q); ok {
				return toMatchBytes(t.Priority)
			}
		}
	case oxm.OXM_OF_IP_DSCP:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv4); ok {
				return toMatchBytes(t.TOS >> 2)
			}
			if t, ok := layer.(*layers.IPv6); ok {
				return toMatchBytes(t.TrafficClass >> 2)
			}
		}
	case oxm.OXM_OF_IP_ECN:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv4); ok {
				return toMatchBytes(t.TOS & 0x03)
			}
			if t, ok := layer.(*layers.IPv6); ok {
				return toMatchBytes(t.TrafficClass & 0x03)
			}
		}
	case oxm.OXM_OF_IP_PROTO:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv4); ok {
				return toMatchBytes(t.Protocol)
			}
			if t, ok := layer.(*layers.IPv6); ok {
				return toMatchBytes(t.NextHeader)
			}
		}
	case oxm.OXM_OF_IPV4_SRC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv4); ok {
				return toMatchBytes(t.SrcIP)
			}
		}
	case oxm.OXM_OF_IPV4_DST:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv4); ok {
				return toMatchBytes(t.DstIP)
			}
		}
	case oxm.OXM_OF_TCP_SRC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.TCP); ok {
				return toMatchBytes(t.SrcPort)
			}
		}
	case oxm.OXM_OF_TCP_DST:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.TCP); ok {
				return toMatchBytes(t.DstPort)
			}
		}
	case oxm.OXM_OF_UDP_SRC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.UDP); ok {
				return toMatchBytes(t.SrcPort)
			}
		}
	case oxm.OXM_OF_UDP_DST:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.UDP); ok {
				return toMatchBytes(t.DstPort)
			}
		}
	case oxm.OXM_OF_SCTP_SRC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.SCTP); ok {
				return toMatchBytes(t.SrcPort)
			}
		}
	case oxm.OXM_OF_SCTP_DST:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.SCTP); ok {
				return toMatchBytes(t.DstPort)
			}
		}
	case oxm.OXM_OF_ICMPV4_TYPE:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv4); ok {
				if buf, err := toMatchBytes(t.TypeCode); err != nil {
					return nil, err
				} else {
					return buf[:1], nil
				}
			}
		}
	case oxm.OXM_OF_ICMPV4_CODE:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv4); ok {
				if buf, err := toMatchBytes(t.TypeCode); err != nil {
					return nil, err
				} else {
					return buf[1:], nil
				}
			}
		}
	case oxm.OXM_OF_ARP_OP:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ARP); ok {
				return toMatchBytes(t.Operation)
			}
		}
	case oxm.OXM_OF_ARP_SPA:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ARP); ok {
				return toMatchBytes(t.SourceProtAddress)
			}
		}
	case oxm.OXM_OF_ARP_TPA:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ARP); ok {
				return toMatchBytes(t.DstProtAddress)
			}
		}
	case oxm.OXM_OF_ARP_SHA:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ARP); ok {
				return toMatchBytes(t.SourceHwAddress)
			}
		}
	case oxm.OXM_OF_ARP_THA:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ARP); ok {
				return toMatchBytes(t.DstHwAddress)
			}
		}
	case oxm.OXM_OF_IPV6_SRC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv6); ok {
				return toMatchBytes(t.SrcIP)
			}
		}
	case oxm.OXM_OF_IPV6_DST:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv6); ok {
				return toMatchBytes(t.DstIP)
			}
		}
	case oxm.OXM_OF_IPV6_FLABEL:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.IPv6); ok {
				return toMatchBytes(t.FlowLabel)
			}
		}
	case oxm.OXM_OF_ICMPV6_TYPE:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv6); ok {
				if buf, err := toMatchBytes(t.TypeCode); err != nil {
					return nil, err
				} else {
					return buf[:1], nil
				}
			}
		}
	case oxm.OXM_OF_ICMPV6_CODE:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv6); ok {
				if buf, err := toMatchBytes(t.TypeCode); err != nil {
					return nil, err
				} else {
					return buf[1:], nil
				}
			}
		}
	case oxm.OXM_OF_IPV6_ND_TARGET:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv6); ok {
				typ := uint8(t.TypeCode >> 8)
				if typ == layers.ICMPv6TypeNeighborSolicitation || typ == layers.ICMPv6TypeNeighborAdvertisement {
					return t.Payload[:16], nil
				}
			}
		}
	case oxm.OXM_OF_IPV6_ND_SLL:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv6); ok {
				typ := uint8(t.TypeCode >> 8)
				if typ == layers.ICMPv6TypeNeighborSolicitation {
					for cur := 16; cur < len(t.Payload); {
						length := int(t.Payload[cur+1]) * 8
						if t.Payload[cur] == 1 { // source link-layer address (RFC 2461 4.6)
							return t.Payload[cur+2 : cur+length], nil
						}
						cur += length
					}
				}
			}
		}
	case oxm.OXM_OF_IPV6_ND_TLL:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.ICMPv6); ok {
				typ := uint8(t.TypeCode >> 8)
				if typ == layers.ICMPv6TypeNeighborAdvertisement {
					for cur := 16; cur < len(t.Payload); {
						length := int(t.Payload[cur+1]) * 8
						if t.Payload[cur] == 2 { // target link-layer address (RFC 2461 4.6)
							return t.Payload[cur+2 : cur+length], nil
						}
						cur += length
					}
				}
			}
		}
	case oxm.OXM_OF_MPLS_LABEL:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.MPLS); ok {
				return toMatchBytes(t.Label)
			}
		}
	case oxm.OXM_OF_MPLS_TC:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.MPLS); ok {
				return toMatchBytes(t.TrafficClass)
			}
		}
	case oxm.OXM_OF_MPLS_BOS:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers.MPLS); ok {
				var bos uint8
				if t.StackBottom {
					bos = uint8(1)
				}
				return toMatchBytes(bos)
			}
		}
	case oxm.OXM_OF_PBB_ISID:
		for _, layer := range self.Layers() {
			if t, ok := layer.(*layers2.PBB); ok {
				ext := make([]byte, 4)
				binary.BigEndian.PutUint32(ext, t.ServiceIdentifier)
				return ext[1:], nil
			}
		}
	case oxm.OXM_OF_TUNNEL_ID:
		return toMatchBytes(self.tunnelId)
	case oxm.OXM_OF_IPV6_EXTHDR:
		exthdr := uint16(0)
		for _, layer := range self.Layers() {
			switch p := layer.(type) {
			case *layers.IPv6:
				if p.NextHeader == layers.IPProtocolNoNextHeader {
					exthdr |= ofp4.OFPIEH_NONEXT
				}
			case *layers.IPSecESP:
				if exthdr&^(ofp4.OFPIEH_HOP|ofp4.OFPIEH_DEST|ofp4.OFPIEH_ROUTER|ofp4.OFPIEH_FRAG|ofp4.OFPIEH_AUTH) != 0 {
					exthdr |= ofp4.OFPIEH_UNSEQ
				}
				if exthdr&ofp4.OFPIEH_ESP != 0 {
					exthdr |= ofp4.OFPIEH_UNREP
				}
				exthdr |= ofp4.OFPIEH_ESP
				//				if p.NextHeader == layers.IPProtocolNoNextHeader {
				//					exthdr |= ofp4.OFPIEH_NONEXT
				//				}
			case *layers.IPSecAH:
				if exthdr&^(ofp4.OFPIEH_HOP|ofp4.OFPIEH_DEST|ofp4.OFPIEH_ROUTER|ofp4.OFPIEH_FRAG) != 0 {
					exthdr |= ofp4.OFPIEH_UNSEQ
				}
				if exthdr&ofp4.OFPIEH_AUTH != 0 {
					exthdr |= ofp4.OFPIEH_UNREP
				}
				exthdr |= ofp4.OFPIEH_AUTH
				if p.NextHeader == layers.IPProtocolNoNextHeader {
					exthdr |= ofp4.OFPIEH_NONEXT
				}
			case *layers.IPv6Destination:
				exthdr |= ofp4.OFPIEH_DEST
				if p.NextHeader == layers.IPProtocolNoNextHeader {
					exthdr |= ofp4.OFPIEH_NONEXT
				}
			case *layers.IPv6Fragment:
				if exthdr&^(ofp4.OFPIEH_HOP|ofp4.OFPIEH_DEST|ofp4.OFPIEH_ROUTER) != 0 {
					exthdr |= ofp4.OFPIEH_UNSEQ
				}
				if exthdr&ofp4.OFPIEH_FRAG != 0 {
					exthdr |= ofp4.OFPIEH_UNREP
				}
				exthdr |= ofp4.OFPIEH_FRAG
				if p.NextHeader == layers.IPProtocolNoNextHeader {
					exthdr |= ofp4.OFPIEH_NONEXT
				}
			case *layers.IPv6Routing:
				if exthdr&^(ofp4.OFPIEH_HOP|ofp4.OFPIEH_DEST) != 0 {
					exthdr |= ofp4.OFPIEH_UNSEQ
				}
				if exthdr&ofp4.OFPIEH_ROUTER != 0 {
					exthdr |= ofp4.OFPIEH_UNREP
				}
				exthdr |= ofp4.OFPIEH_ROUTER
				if p.NextHeader == layers.IPProtocolNoNextHeader {
					exthdr |= ofp4.OFPIEH_NONEXT
				}
			case *layers.IPv6HopByHop:
				if exthdr != 0 {
					exthdr |= ofp4.OFPIEH_UNSEQ
				}
				if exthdr&ofp4.OFPIEH_HOP != 0 {
					exthdr |= ofp4.OFPIEH_UNREP
				}
				exthdr |= ofp4.OFPIEH_HOP
				if p.NextHeader == layers.IPProtocolNoNextHeader {
					exthdr |= ofp4.OFPIEH_NONEXT
				}
			}
		}
		return toMatchBytes(exthdr)
	}
	return nil, fmt.Errorf("oxm value not found for %d", oxmType)
}
예제 #17
0
파일: match_nxm.go 프로젝트: hkwi/gopenflow
func nxmDefs(hdr uint32) (length int, mayMask bool) {
	switch oxm.Header(hdr).Type() {
	case NXM_OF_IN_PORT:
		return 2, false
	case NXM_OF_ETH_DST:
		return 6, false
	case NXM_OF_ETH_SRC:
		return 6, false
	case NXM_OF_ETH_TYPE:
		return 2, false
	case NXM_OF_VLAN_TCI:
		return 4, false
	case NXM_OF_IP_TOS:
		return 1, false
	case NXM_OF_IP_PROTO:
		return 1, false
	case NXM_OF_IP_SRC:
		return 4, false
	case NXM_OF_IP_DST:
		return 4, false
	case NXM_OF_TCP_SRC:
		return 2, false
	case NXM_OF_TCP_DST:
		return 2, false
	case NXM_OF_UDP_SRC:
		return 2, false
	case NXM_OF_UDP_DST:
		return 2, false
	case NXM_OF_ICMP_TYPE:
		return 1, false
	case NXM_OF_ICMP_CODE:
		return 1, false
	case NXM_OF_ARP_OP:
		return 2, false
	case NXM_OF_ARP_SPA:
		return 4, false
	case NXM_OF_ARP_TPA:
		return 4, false
	case NXM_NX_REG0:
		return 4, true
	case NXM_NX_REG1:
		return 4, true
	case NXM_NX_REG2:
		return 4, true
	case NXM_NX_REG3:
		return 4, true
	case NXM_NX_REG4:
		return 4, true
	case NXM_NX_REG5:
		return 4, true
	case NXM_NX_REG6:
		return 4, true
	case NXM_NX_REG7:
		return 4, true
	case NXM_NX_TUN_ID:
		return 8, true
	case NXM_NX_ARP_SHA:
		return 6, true
	case NXM_NX_ARP_THA:
		return 6, true
	case NXM_NX_IPV6_SRC:
		return 16, true
	case NXM_NX_IPV6_DST:
		return 16, true
	case NXM_NX_ICMPV6_TYPE:
		return 1, true
	case NXM_NX_ICMPV6_CODE:
		return 1, true
	case NXM_NX_ND_TARGET:
		return 16, true
	case NXM_NX_ND_SLL:
		return 6, true
	case NXM_NX_ND_TLL:
		return 6, true
	case NXM_NX_IP_FRAG:
		return 1, true
	case NXM_NX_IPV6_LABEL:
		return 4, true
	case NXM_NX_IP_ECN:
		return 1, true
	case NXM_NX_IP_TTL:
		return 1, true
	case NXM_NX_TUN_IPV4_SRC:
		return 4, true
	case NXM_NX_TUN_IPV4_DST:
		return 4, true
	case NXM_NX_PKT_MARK:
		return 4, true
	case NXM_NX_TCP_FLAGS:
		return 2, true
	case NXM_NX_DP_HASH:
		return 4, true
	case NXM_NX_RECIRC_ID:
		return 4, true
	case NXM_NX_CONJ_ID:
		return 4, true
	case NXM_NX_TUN_GBP_ID:
		return 2, true
	case NXM_NX_TUN_GBP_FLAGS:
		return 1, true
	default:
		return 0, false
	}
}