diff --git a/app/test-sniffer/util.go b/app/test-sniffer/util.go index fbdb1c1..dc28006 100644 --- a/app/test-sniffer/util.go +++ b/app/test-sniffer/util.go @@ -57,9 +57,9 @@ func rssEthVlanIPv4(pid ethdev.Port, conf *ethdev.RssConf) (*flow.Flow, error) { attr := &flow.Attr{Ingress: true} pattern := []flow.Item{ - {Spec: flow.ItemTypeEth}, // Ethernet - {Spec: flow.ItemTypeVlan}, // VLAN - {Spec: flow.ItemTypeIPv4}, // IPv4 + {Spec: &flow.ItemEth{}}, // Ethernet + {Spec: &flow.ItemVlan{}}, // VLAN + {Spec: &flow.ItemIPv4{}}, // IPv4 } actions := []flow.Action{ @@ -83,9 +83,9 @@ func mlxRssEthVlanIPv4(pid ethdev.Port, conf *ethdev.RssConf) (*flow.Flow, error attr := &flow.Attr{Ingress: true} pattern := []flow.Item{ - {Spec: flow.ItemTypeEth}, // Ethernet - {Spec: flow.ItemTypeVlan}, // VLAN - {Spec: flow.ItemTypeIPv4}, // IPv4 + {Spec: &flow.ItemEth{}}, // Ethernet + {Spec: &flow.ItemVlan{}}, // VLAN + {Spec: &flow.ItemIPv4{}}, // IPv4 } var info ethdev.DevInfo diff --git a/ethdev/flow/action.go b/ethdev/flow/action.go index baf4e66..aadce2e 100644 --- a/ethdev/flow/action.go +++ b/ethdev/flow/action.go @@ -6,20 +6,13 @@ package flow #include */ import "C" -import "unsafe" +import ( + "github.com/yerden/go-dpdk/common" +) // ActionType is the rte_flow_action type. type ActionType uint32 -// Reload implements Action interface. -func (t ActionType) Reload() {} - -// Pointer implements Action interface. -func (t ActionType) Pointer() unsafe.Pointer { return nil } - -// Type implements Action interface. -func (t ActionType) Type() ActionType { return t } - // Action is the definition of a single action. // // A list of actions is terminated by a END action. @@ -27,13 +20,8 @@ func (t ActionType) Type() ActionType { return t } // For simple actions without a configuration object, conf remains // NULL. type Action interface { - // Pointer returns a valid C pointer to underlying struct. - Pointer() unsafe.Pointer - - // Reload is used to apply changes so that the underlying struct - // reflects the up-to-date configuration. - Reload() + common.Transformer - // Type returns implemented rte_flow_action_* struct. - Type() ActionType + // ActionType returns implemented rte_flow_action_* struct. + ActionType() ActionType } diff --git a/ethdev/flow/action_queue.go b/ethdev/flow/action_queue.go index bd8c808..7b255e6 100644 --- a/ethdev/flow/action_queue.go +++ b/ethdev/flow/action_queue.go @@ -7,7 +7,9 @@ package flow */ import "C" import ( - "runtime" + "unsafe" + + "github.com/yerden/go-dpdk/common" ) var _ Action = (*ActionQueue)(nil) @@ -15,19 +17,18 @@ var _ Action = (*ActionQueue)(nil) // ActionQueue implements Action which assigns packets to a given // queue index. type ActionQueue struct { - cPointer Index uint16 } -// Reload implements Action interface. -func (action *ActionQueue) Reload() { - cptr := (*C.struct_rte_flow_action_queue)(action.createOrRet(C.sizeof_struct_rte_flow_action_queue)) - - cptr.index = C.uint16_t(action.Index) - runtime.SetFinalizer(action, (*ActionQueue).free) +// Transform implements Action interface. +func (action *ActionQueue) Transform(alloc common.Allocator) (unsafe.Pointer, func(unsafe.Pointer)) { + s := &C.struct_rte_flow_action_queue{ + index: C.ushort(action.Index), + } + return common.TransformPOD(alloc, s) } -// Type implements Action interface. -func (action *ActionQueue) Type() ActionType { +// ActionType implements Action interface. +func (action *ActionQueue) ActionType() ActionType { return ActionTypeQueue } diff --git a/ethdev/flow/action_rss.go b/ethdev/flow/action_rss.go index ef83a81..ff81e2f 100644 --- a/ethdev/flow/action_rss.go +++ b/ethdev/flow/action_rss.go @@ -7,8 +7,9 @@ package flow */ import "C" import ( - "runtime" "unsafe" + + "github.com/yerden/go-dpdk/common" ) var _ Action = (*ActionRSS)(nil) @@ -34,61 +35,43 @@ type ActionRSS struct { Key []byte Level uint32 Types uint64 - - cptr *C.struct_rte_flow_action_rss -} - -func (action *ActionRSS) free() { - cptr := action.cptr - C.free(unsafe.Pointer(cptr.key)) - C.free(unsafe.Pointer(cptr.queue)) - C.free(unsafe.Pointer(cptr)) } -// Reload implements Action interface. -func (action *ActionRSS) Reload() { - // allocate if needed - cptr := action.cptr - if cptr == nil { - cptr = (*C.struct_rte_flow_action_rss)(C.malloc(C.sizeof_struct_rte_flow_action_rss)) - *cptr = C.struct_rte_flow_action_rss{} - action.cptr = cptr - } +// Transform implements Action interface. +func (action *ActionRSS) Transform(alloc common.Allocator) (unsafe.Pointer, func(unsafe.Pointer)) { + cptr := (*C.struct_rte_flow_action_rss)(alloc.Malloc(C.sizeof_struct_rte_flow_action_rss)) + *cptr = C.struct_rte_flow_action_rss{} // set queues if len(action.Queues) > 0 { - sz := C.size_t(len(action.Queues)) * C.size_t(unsafe.Sizeof(action.Queues[0])) - cQueues := C.malloc(sz) - C.memcpy(cQueues, unsafe.Pointer(&action.Queues[0]), sz) - C.free(unsafe.Pointer(cptr.queue)) + var x *C.uint16_t + common.CallocT(alloc, &x, len(action.Queues)) + queues := unsafe.Slice(x, len(action.Queues)) + for i := range queues { + queues[i] = C.uint16_t(action.Queues[i]) + } cptr.queue_num = C.uint32_t(len(action.Queues)) - cptr.queue = (*C.uint16_t)(cQueues) } // set key if len(action.Key) > 0 { - sz := C.size_t(len(action.Key)) - cKey := C.malloc(sz) - C.memcpy(cKey, unsafe.Pointer(&action.Key[0]), sz) - C.free(unsafe.Pointer(cptr.key)) cptr.key_len = C.uint32_t(len(action.Key)) - cptr.key = (*C.uint8_t)(cKey) + cptr.key = (*C.uchar)(common.CBytes(alloc, action.Key)) } cptr.level = C.uint32_t(action.Level) cptr.types = C.uint64_t(action.Types) cptr._func = uint32(action.Func) - runtime.SetFinalizer(action, nil) - runtime.SetFinalizer(action, (*ActionRSS).free) -} - -// Pointer implements Action interface. -func (action *ActionRSS) Pointer() unsafe.Pointer { - return unsafe.Pointer(action.cptr) + return unsafe.Pointer(cptr), func(p unsafe.Pointer) { + cptr = (*C.struct_rte_flow_action_rss)(p) + alloc.Free(unsafe.Pointer(cptr.key)) + alloc.Free(unsafe.Pointer(cptr.queue)) + alloc.Free(p) + } } -// Type implements Action interface. -func (action *ActionRSS) Type() ActionType { +// ActionType implements Action interface. +func (action *ActionRSS) ActionType() ActionType { return ActionTypeRss } diff --git a/ethdev/flow/flow.go b/ethdev/flow/flow.go index 9d237d6..f1d7517 100644 --- a/ethdev/flow/flow.go +++ b/ethdev/flow/flow.go @@ -8,8 +8,6 @@ package flow import "C" import ( - "runtime" - "github.com/yerden/go-dpdk/common" "github.com/yerden/go-dpdk/ethdev" ) @@ -23,40 +21,54 @@ const _ uintptr = -uintptr(ActionTypeEnd) // Flow is the opaque flow handle. type Flow C.struct_rte_flow -// allocate c-style list of rte_flow_item's. -func cPattern(pattern []Item) []C.struct_rte_flow_item { - pat := make([]C.struct_rte_flow_item, len(pattern)+1) +type cArgs struct { + pid C.ushort + attr C.struct_rte_flow_attr + pat *C.struct_rte_flow_item + act *C.struct_rte_flow_action + e *C.struct_rte_flow_error +} + +func doFancy(port ethdev.Port, attr *Attr, pattern []Item, actions []Action, flowErr *Error, fn func(*cArgs)) { + alloc := common.NewAllocatorSession(&common.StdAlloc{}) + defer alloc.Flush() + // patterns + var pat []C.struct_rte_flow_item for i := range pattern { - typ := pattern[i].Spec.Type() - pat[i]._type = uint32(typ) - pattern[i].Spec.Reload() - pat[i].spec = pattern[i].Spec.Pointer() - if item := pattern[i].Mask; item != nil { - item.Reload() - pat[i].mask = item.Pointer() - } - if item := pattern[i].Last; item != nil { - item.Reload() - pat[i].last = item.Pointer() - } + p := &pattern[i] + cPat := C.struct_rte_flow_item{} + cPat._type = uint32(p.Spec.ItemType()) + cPat.spec, _ = pattern[i].Spec.Transform(alloc) + cPat.last, _ = pattern[i].Last.Transform(alloc) + cPat.mask, _ = pattern[i].Mask.Transform(alloc) + pat = append(pat, cPat) } - return pat -} + // patterns finalizer + pat = append(pat, C.struct_rte_flow_item{}) -// allocate c-style list of rte_flow_action's. -func cActions(actions []Action) []C.struct_rte_flow_action { - act := make([]C.struct_rte_flow_action, len(actions)+1) + // actions + var act []C.struct_rte_flow_action + for _, p := range actions { + cAction := C.struct_rte_flow_action{} + cAction._type = uint32(p.ActionType()) + cAction.conf, _ = p.Transform(alloc) + act = append(act, cAction) + } + + // actions finalizer + act = append(act, C.struct_rte_flow_action{}) - for i := range actions { - typ := actions[i].Type() - act[i]._type = uint32(typ) - actions[i].Reload() - act[i].conf = actions[i].Pointer() + args := &cArgs{ + pid: C.ushort(port), + attr: attr.cvtAttr(), + pat: &pat[0], + act: &act[0], + e: (*C.struct_rte_flow_error)(flowErr), } - return act + fn(args) } // Create a flow rule on a given port. @@ -71,18 +83,15 @@ func cActions(actions []Action) []C.struct_rte_flow_action { // Returns a valid handle in case of success, NULL otherwise and // rte_errno is set to the positive version of one of the error codes // defined for rte_flow_validate(). -func Create(port ethdev.Port, attr *Attr, pattern []Item, actions []Action, flowErr *Error) (*Flow, error) { - pat := cPattern(pattern) - act := cActions(actions) - cAttr := attr.cvtAttr() - f := C.rte_flow_create(C.ushort(port), &cAttr, &pat[0], &act[0], (*C.struct_rte_flow_error)(flowErr)) - runtime.KeepAlive(pattern) - runtime.KeepAlive(actions) - if f == nil { - return nil, common.RteErrno() - } - - return (*Flow)(f), nil +func Create(port ethdev.Port, attr *Attr, pattern []Item, actions []Action, flowErr *Error) (f *Flow, err error) { + doFancy(port, attr, pattern, actions, flowErr, func(args *cArgs) { + if p := C.rte_flow_create(args.pid, &args.attr, args.pat, args.act, args.e); p != nil { + f = (*Flow)(p) + } else { + err = common.RteErrno() + } + }) + return } // Validate checks whether a flow rule can be created on a given port. @@ -99,14 +108,12 @@ func Create(port ethdev.Port, attr *Attr, pattern []Item, actions []Action, flow // made in the meantime and no device parameter affecting flow rules // in any way are modified, due to possible collisions or resource // limitations (although in such cases EINVAL should not be returned). -func Validate(port ethdev.Port, attr *Attr, pattern []Item, actions []Action, flowErr *Error) error { - pat := cPattern(pattern) - act := cActions(actions) - cAttr := attr.cvtAttr() - ret := C.rte_flow_validate(C.ushort(port), &cAttr, &pat[0], &act[0], (*C.struct_rte_flow_error)(flowErr)) - runtime.KeepAlive(pattern) - runtime.KeepAlive(actions) - return common.IntToErr(ret) +func Validate(port ethdev.Port, attr *Attr, pattern []Item, actions []Action, flowErr *Error) (err error) { + doFancy(port, attr, pattern, actions, flowErr, func(args *cArgs) { + rc := C.rte_flow_validate(args.pid, &args.attr, args.pat, args.act, args.e) + err = common.IntErr(int64(rc)) + }) + return } // Destroy a flow rule on a given port. diff --git a/ethdev/flow/flow_test.go b/ethdev/flow/flow_test.go index 7e2e97c..12bdc4d 100644 --- a/ethdev/flow/flow_test.go +++ b/ethdev/flow/flow_test.go @@ -8,13 +8,3 @@ func assert(t testing.TB, expected bool, args ...interface{}) { t.Fatal(args...) } } - -func TestCPattern(t *testing.T) { - pattern := []Item{ - {Spec: &ItemIPv4{}, Mask: &ItemIPv4{}}, - } - - pat := cPattern(pattern) - assert(t, pat != nil) - -} diff --git a/ethdev/flow/item.go b/ethdev/flow/item.go index c557839..fa1b204 100644 --- a/ethdev/flow/item.go +++ b/ethdev/flow/item.go @@ -6,39 +6,26 @@ package flow #include */ import "C" -import "unsafe" +import ( + "unsafe" + + "github.com/yerden/go-dpdk/common" +) // ItemType represents rte_flow_item type. type ItemType uint32 -// Reload implements ItemStruct interface. -func (t ItemType) Reload() {} - -// Pointer implements ItemStruct interface. -func (t ItemType) Pointer() unsafe.Pointer { return nil } - -// Type implements ItemStruct interface. -func (t ItemType) Type() ItemType { return t } - -// Mask implements ItemStruct interface. -func (t ItemType) Mask() unsafe.Pointer { return nil } - -// ItemStruct should be implemented to specify in Item. -type ItemStruct interface { - // Pointer returns a valid C pointer to underlying struct. - Pointer() unsafe.Pointer - - // Reload is used to apply changes so that the underlying struct - // reflects the up-to-date configuration. - Reload() +// ItemValue should be implemented to specify in Item. +type ItemValue interface { + common.Transformer - // Type returns implemented rte_flow_item_* struct. - Type() ItemType + // ItemType returns implemented rte_flow_item_* struct. + ItemType() ItemType // Mask returns pointer to rte_flow_item_*_mask variables. They // should not be changed by user so Mask returns pointer to C // struct. - Mask() unsafe.Pointer + DefaultMask() unsafe.Pointer } // Item is the matching pattern item definition. @@ -77,5 +64,5 @@ type ItemStruct interface { // Go: you may also specify ItemType as a Spec field if you don't want // to specify any pattern for the item. type Item struct { - Spec, Last, Mask ItemStruct + Spec, Last, Mask ItemValue } diff --git a/ethdev/flow/item_eth.go b/ethdev/flow/item_eth.go index 49c0b04d..cfa65d7 100644 --- a/ethdev/flow/item_eth.go +++ b/ethdev/flow/item_eth.go @@ -28,20 +28,15 @@ void set_has_vlan(struct rte_flow_item_eth *item, uint32_t b) { item->has_vlan = b; } -static const struct rte_flow_item_eth *get_item_eth_mask() { - return &rte_flow_item_eth_mask; -} - */ import "C" import ( - "net" - "reflect" - "runtime" "unsafe" + + "github.com/yerden/go-dpdk/common" ) -var _ ItemStruct = (*ItemEth)(nil) +var _ ItemValue = (*ItemEth)(nil) // ItemEth matches an Ethernet header. // @@ -59,54 +54,34 @@ var _ ItemStruct = (*ItemEth)(nil) // possible to leave the two fields unused. If this is the case, both // tagged and untagged packets will match the pattern. type ItemEth struct { - cPointer HasVlan bool - Src, Dst net.HardwareAddr + Src, Dst [6]byte EtherType uint16 } -// Reload implements ItemStruct interface. -func (item *ItemEth) Reload() { - cptr := (*C.struct_rte_flow_item_eth)(item.createOrRet(C.sizeof_struct_rte_flow_item_eth)) - - var u uint32 - if item.HasVlan { - u = 1 +func boolU32(b bool) (x C.uint32_t) { + if b { + x = 1 } - C.set_has_vlan(cptr, C.uint32_t(u)) - - hdr := (*C.struct_rte_ether_hdr)(off(unsafe.Pointer(cptr), C.ITEM_ETH_OFF_HDR)) - - if len(item.Src) > 0 { - p := off(unsafe.Pointer(hdr), C.ETHER_HDR_OFF_SRC) - setAddr((*C.struct_rte_ether_addr)(p), item.Src) - } - - if len(item.Dst) > 0 { - p := off(unsafe.Pointer(hdr), C.ETHER_HDR_OFF_DST) - setAddr((*C.struct_rte_ether_addr)(p), item.Dst) - } - - beU16(item.EtherType, unsafe.Pointer(&hdr.ether_type)) - - runtime.SetFinalizer(item, (*ItemEth).free) + return } -func setAddr(p *C.struct_rte_ether_addr, addr net.HardwareAddr) { - var hwaddr []byte - sh := (*reflect.SliceHeader)(unsafe.Pointer(&hwaddr)) - sh.Data = uintptr(unsafe.Pointer(&p.addr_bytes[0])) - sh.Len = len(p.addr_bytes) - sh.Cap = sh.Len - copy(hwaddr, addr) +// Transform implements Action interface. +func (item *ItemEth) Transform(alloc common.Allocator) (unsafe.Pointer, func(unsafe.Pointer)) { + cptr := &C.struct_rte_flow_item_eth{} + hdr := (*C.struct_rte_ether_addr)(unsafe.Add(unsafe.Pointer(cptr), C.ITEM_ETH_OFF_HDR)) + *(*[6]byte)(unsafe.Add(unsafe.Pointer(hdr), C.ETHER_HDR_OFF_SRC)) = item.Src + *(*[6]byte)(unsafe.Add(unsafe.Pointer(hdr), C.ETHER_HDR_OFF_DST)) = item.Dst + C.set_has_vlan(cptr, boolU32(item.HasVlan)) + return common.TransformPOD(alloc, cptr) } -// Type implements ItemStruct interface. -func (item *ItemEth) Type() ItemType { +// ItemType implements ItemValue interface. +func (item *ItemEth) ItemType() ItemType { return ItemTypeEth } -// Mask implements ItemStruct interface. -func (item *ItemEth) Mask() unsafe.Pointer { - return unsafe.Pointer(C.get_item_eth_mask()) +// DefaultMask implements ItemStruct interface. +func (item *ItemEth) DefaultMask() unsafe.Pointer { + return unsafe.Pointer(&C.rte_flow_item_eth_mask) } diff --git a/ethdev/flow/item_ipv4.go b/ethdev/flow/item_ipv4.go index 9049545..36a1909 100644 --- a/ethdev/flow/item_ipv4.go +++ b/ethdev/flow/item_ipv4.go @@ -3,6 +3,7 @@ package flow /* #include #include +#include #include enum { @@ -16,8 +17,9 @@ static const struct rte_flow_item_ipv4 *get_item_ipv4_mask() { */ import "C" import ( - "runtime" "unsafe" + + "github.com/yerden/go-dpdk/common" ) // IPv4 represents a raw IPv4 address. @@ -37,50 +39,31 @@ type IPv4Header struct { DstAddr IPv4 /* Destination address. */ } +const _ uintptr = unsafe.Sizeof(IPv4Header{}) - C.sizeof_struct_rte_ipv4_hdr +const _ uintptr = C.sizeof_struct_rte_ipv4_hdr - unsafe.Sizeof(IPv4Header{}) + // ItemIPv4 matches an IPv4 header. // // Note: IPv4 options are handled by dedicated pattern items. type ItemIPv4 struct { - cPointer - Header IPv4Header } -var _ ItemStruct = (*ItemIPv4)(nil) - -// Reload implements ItemStruct interface. -func (item *ItemIPv4) Reload() { - cptr := (*C.struct_rte_flow_item_ipv4)(item.createOrRet(C.sizeof_struct_rte_flow_item_ipv4)) - cvtIPv4Header(&cptr.hdr, &item.Header) - runtime.SetFinalizer(item, (*ItemIPv4).free) -} - -func cvtIPv4Header(dst *C.struct_rte_ipv4_hdr, src *IPv4Header) { - setIPv4HdrVersionIHL(dst, src) - - dst.type_of_service = C.uint8_t(src.ToS) - beU16(src.TotalLength, unsafe.Pointer(&dst.total_length)) - beU16(src.ID, unsafe.Pointer(&dst.packet_id)) - beU16(src.FragmentOffset, unsafe.Pointer(&dst.fragment_offset)) - dst.time_to_live = C.uint8_t(src.TTL) - dst.next_proto_id = C.uint8_t(src.Proto) - beU16(src.Checksum, unsafe.Pointer(&dst.hdr_checksum)) - - dst.src_addr = *(*C.rte_be32_t)(unsafe.Pointer(&src.SrcAddr[0])) - dst.dst_addr = *(*C.rte_be32_t)(unsafe.Pointer(&src.DstAddr[0])) -} +var _ ItemValue = (*ItemIPv4)(nil) -func setIPv4HdrVersionIHL(dst *C.struct_rte_ipv4_hdr, src *IPv4Header) { - p := off(unsafe.Pointer(dst), C.IPv4_HDR_OFF_DST_VERSION_IHL) - *(*C.uint8_t)(p) = (C.uchar)(src.VersionIHL) +// Transform implements Action interface. +func (item *ItemIPv4) Transform(alloc common.Allocator) (unsafe.Pointer, func(unsafe.Pointer)) { + ptr := &C.struct_rte_flow_item_ipv4{} + ptr.hdr = *(*C.struct_rte_ipv4_hdr)(unsafe.Pointer(&item.Header)) + return common.TransformPOD(alloc, ptr) } -// Type implements ItemStruct interface. -func (item *ItemIPv4) Type() ItemType { +// ItemType implements ItemValue interface. +func (item *ItemIPv4) ItemType() ItemType { return ItemTypeIPv4 } -// Mask implements ItemStruct interface. -func (item *ItemIPv4) Mask() unsafe.Pointer { - return unsafe.Pointer(C.get_item_ipv4_mask()) +// DefaultMask implements ItemStruct interface. +func (item *ItemIPv4) DefaultMask() unsafe.Pointer { + return unsafe.Pointer(&C.rte_flow_item_ipv4_mask) } diff --git a/ethdev/flow/item_udp.go b/ethdev/flow/item_udp.go index 7923a69..0d75193 100644 --- a/ethdev/flow/item_udp.go +++ b/ethdev/flow/item_udp.go @@ -4,16 +4,14 @@ package flow #include #include #include - -static const struct rte_flow_item_udp *get_item_udp_mask() { - return &rte_flow_item_udp_mask; -} +#include */ import "C" import ( - "runtime" "unsafe" + + "github.com/yerden/go-dpdk/common" ) // UDPHeader represents UDP header format. @@ -24,35 +22,29 @@ type UDPHeader struct { Checksum uint16 /* UDP datagram checksum */ } +const _ uintptr = unsafe.Sizeof(UDPHeader{}) - C.sizeof_struct_rte_udp_hdr +const _ uintptr = C.sizeof_struct_rte_udp_hdr - unsafe.Sizeof(UDPHeader{}) + // ItemUDP matches an UDP header. type ItemUDP struct { - cPointer - Header UDPHeader } -var _ ItemStruct = (*ItemUDP)(nil) - -// Reload implements ItemStruct interface. -func (item *ItemUDP) Reload() { - cptr := (*C.struct_rte_flow_item_udp)(item.createOrRet(C.sizeof_struct_rte_flow_item_udp)) - cvtUDPHeader(&cptr.hdr, &item.Header) - runtime.SetFinalizer(item, (*ItemUDP).free) -} +var _ ItemValue = (*ItemUDP)(nil) -func cvtUDPHeader(dst *C.struct_rte_udp_hdr, src *UDPHeader) { - beU16(uint16(src.SrcPort), unsafe.Pointer(&dst.src_port)) - beU16(uint16(src.DstPort), unsafe.Pointer(&dst.dst_port)) - beU16(src.Length, unsafe.Pointer(&dst.dgram_len)) - beU16(src.Checksum, unsafe.Pointer(&dst.dgram_cksum)) +// Transform implements Action interface. +func (item *ItemUDP) Transform(alloc common.Allocator) (unsafe.Pointer, func(unsafe.Pointer)) { + ptr := &C.struct_rte_flow_item_udp{} + ptr.hdr = *(*C.struct_rte_udp_hdr)(unsafe.Pointer(&item.Header)) + return common.TransformPOD(alloc, ptr) } -// Type implements ItemStruct interface. -func (item *ItemUDP) Type() ItemType { +// ItemType implements ItemValue interface. +func (item *ItemUDP) ItemType() ItemType { return ItemTypeUDP } -// Mask implements ItemStruct interface. -func (item *ItemUDP) Mask() unsafe.Pointer { - return unsafe.Pointer(C.get_item_udp_mask()) +// DefaultMask implements ItemStruct interface. +func (item *ItemUDP) DefaultMask() unsafe.Pointer { + return unsafe.Pointer(&C.rte_flow_item_udp_mask) } diff --git a/ethdev/flow/item_vlan.go b/ethdev/flow/item_vlan.go index 31c2dff..8c2a1f2 100644 --- a/ethdev/flow/item_vlan.go +++ b/ethdev/flow/item_vlan.go @@ -10,10 +10,6 @@ enum { ITEM_VLAN_OFF_HDR = offsetof(struct rte_flow_item_vlan, hdr), }; -static const void *get_item_vlan_mask() { - return &rte_flow_item_vlan_mask; -} - static void set_has_more_vlan(struct rte_flow_item_vlan *item, uint32_t d) { item->has_more_vlan = d; } @@ -21,11 +17,12 @@ static void set_has_more_vlan(struct rte_flow_item_vlan *item, uint32_t d) { */ import "C" import ( - "runtime" "unsafe" + + "github.com/yerden/go-dpdk/common" ) -var _ ItemStruct = (*ItemVlan)(nil) +var _ ItemValue = (*ItemVlan)(nil) // ItemVlan matches an 802.1Q/ad VLAN tag. // @@ -37,15 +34,14 @@ var _ ItemStruct = (*ItemVlan)(nil) // If the eth_proto of hdr and has_more_vlan fields are not specified, then any // tagged packets will match the pattern. type ItemVlan struct { - cPointer HasMoreVlan bool TCI uint16 InnerType uint16 } -// Reload implements ItemStruct interface. -func (item *ItemVlan) Reload() { - cptr := (*C.struct_rte_flow_item_vlan)(item.createOrRet(C.sizeof_struct_rte_flow_item_vlan)) +// Transform implements Action interface. +func (item *ItemVlan) Transform(alloc common.Allocator) (unsafe.Pointer, func(unsafe.Pointer)) { + cptr := &C.struct_rte_flow_item_vlan{} if item.HasMoreVlan { C.set_has_more_vlan(cptr, 1) @@ -53,19 +49,18 @@ func (item *ItemVlan) Reload() { C.set_has_more_vlan(cptr, 0) } - hdr := (*C.struct_rte_vlan_hdr)(off(unsafe.Pointer(cptr), C.ITEM_VLAN_OFF_HDR)) - beU16(item.TCI, unsafe.Pointer(&hdr.vlan_tci)) - beU16(item.InnerType, unsafe.Pointer(&hdr.eth_proto)) - - runtime.SetFinalizer(item, (*ItemVlan).free) + hdr := (*C.struct_rte_vlan_hdr)(unsafe.Add(unsafe.Pointer(cptr), C.ITEM_VLAN_OFF_HDR)) + hdr.vlan_tci = C.ushort(item.TCI) + hdr.eth_proto = C.ushort(item.InnerType) + return common.TransformPOD(alloc, cptr) } -// Type implements ItemStruct interface. -func (item *ItemVlan) Type() ItemType { +// ItemType implements ItemValue interface. +func (item *ItemVlan) ItemType() ItemType { return ItemTypeVlan } -// Mask implements ItemStruct interface. -func (item *ItemVlan) Mask() unsafe.Pointer { - return C.get_item_vlan_mask() +// DefaultMask implements ItemStruct interface. +func (item *ItemVlan) DefaultMask() unsafe.Pointer { + return unsafe.Pointer(&C.rte_flow_item_vlan_mask) } diff --git a/ethdev/flow/utils.go b/ethdev/flow/utils.go deleted file mode 100644 index eac5868..0000000 --- a/ethdev/flow/utils.go +++ /dev/null @@ -1,57 +0,0 @@ -package flow - -/* -#include -#include -#include -*/ -import "C" -import ( - "encoding/binary" - "reflect" - "unsafe" -) - -func off(p unsafe.Pointer, d uintptr) unsafe.Pointer { - return unsafe.Pointer(uintptr(p) + d) -} - -func beU16(n uint16, p unsafe.Pointer) { - var d []byte - sh := (*reflect.SliceHeader)(unsafe.Pointer(&d)) - sh.Data = uintptr(p) - sh.Len = 2 - sh.Cap = sh.Len - binary.BigEndian.PutUint16(d, n) -} - -func beU32(n uint32, p unsafe.Pointer) { - var d []byte - sh := (*reflect.SliceHeader)(unsafe.Pointer(&d)) - sh.Data = uintptr(p) - sh.Len = 4 - sh.Cap = sh.Len - binary.BigEndian.PutUint32(d, n) -} - -type cPointer struct { - cptr unsafe.Pointer -} - -func (p *cPointer) free() { - C.free(p.cptr) -} - -// Pointer is the blanket implementation of ItemStruct/Action. -func (p *cPointer) Pointer() unsafe.Pointer { - return p.cptr -} - -func (p *cPointer) createOrRet(n C.ulong) unsafe.Pointer { - if p.cptr == nil { - p.cptr = C.malloc(n) - C.memset(p.cptr, 0, n) - } - - return p.cptr -}