* Re: [dpdk-dev] [PATCH] mk: enable next abi in static libs
2015-07-06 18:22 9% ` Neil Horman
@ 2015-07-06 21:44 9% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-07-06 21:44 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-07-06 14:22, Neil Horman:
> On Mon, Jul 06, 2015 at 03:49:50PM +0200, Thomas Monjalon wrote:
> > 2015-07-06 09:35, Neil Horman:
> > > On Mon, Jul 06, 2015 at 03:18:51PM +0200, Thomas Monjalon wrote:
> > > > Any comment or ack?
> > > >
> > > > 2015-07-03 00:05, Thomas Monjalon:
> > > > > When a change makes really hard to keep ABI compatibility,
> > > > > instead of waiting next release to break the ABI, it is smoother
> > > > > to introduce the new code and enable it only for static libraries.
> > > > > The flag RTE_NEXT_ABI may be used to "ifdef" the new code.
> > > > > When the release is out, a dynamically linked application can use
> > > > > the new shared libraries without rebuild while developpers can prepare
> > > > > their application for the next ABI by reading the deprecation notice
> > > > > and easily testing the new code.
> > > > > When starting the next release cycle, the "ifdefs" will be removed
> > > > > and the ABI break will be marked by incrementing LIBABIVER.
> > > > >
> > > > > The new option CONFIG_RTE_NEXT_ABI is not defined in the configuration
> > > > > templates because it is deduced from CONFIG_RTE_BUILD_SHARED_LIB.
> > > > > It is automatically enabled for static libraries and disabled for
> > > > > shared libraries.
> > > > > It can be forced to another value by editing the generated .config file.
> > > > > It shouldn't be enabled for shared libraries because it would break the
> > > > > ABI without changing the version number LIBABIVER. That's why a warning
> > > > > is printed in this case.
> > > > >
> > > > > The guideline is also updated to integrate this new possibility.
[...]
> I'd be ok with it iff:
>
> 1) It applies to static and shared ABI's together. That is to say that setting
> the NEXT_ABI config flag creates the same ABI changes regardless of other build
> configuration. It needs to be used in such a way that a consistent ABI is
> presented when set, otherwise it won't be useful.
Yes the option trigger exactly the same ABI for static and shared libraries.
But it's too complicated (at least for 2.1) to make LIBABIVER and version map
dependant of this build-time option.
That's why, it should not be enabled to deploy shared libraries, though it can
be used for tests and development.
As static libraries are almost never packaged, they will be built and linked
at the same time. That's why users of static libraries tend to prefer the
newest ABI, which is the default in this case.
> 2) It only applies to the next ABI. That is to say, it can't be a hodgepodge of
> the next ABI and the one after that, and the one after that, or it won't provide
> an appropriate preview for anyone.
If you mean the next ABI must be promoted as the standard ABI in the next release,
yes: ifdefs will be cleaned when starting a new release.
Thanks, I learnt the english word hodgepodge :)
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [PATCH 1/2] eal/persistent: new library to hold memory region after program exit
@ 2015-07-06 19:19 1% ` Stephen Hemminger
0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2015-07-06 19:19 UTC (permalink / raw)
To: leeopop; +Cc: dev
Am I right, this library is using Unix shared memory to get
persistent storage. That is going to be slower and more worrying,
the kernel makes no guarantees that virtual to physical mapping
will not change.
There is also an ABI issue in this patch. You are introducing a new
API here, so the symbol should go in a new 2.1 section
> + if((len / RTE_PGSIZE_4K) > 1)
> + {
> + shmget_flag |= SHM_HUGETLB;
> + }
Please follow kernel coding style. This is one of many examples that
needs to be fixed before accepting.
ERROR: "foo* bar" should be "foo *bar"
#166: FILE: lib/librte_eal/common/include/rte_pci.h:210:
+ void* priv; /**< Private data. */
ERROR: "foo* bar" should be "foo *bar"
#195: FILE: lib/librte_eal/common/include/rte_persistent_mem.h:20:
+extern void* persistent_allocated_memory[RTE_MAX_NUMA_NODES][RTE_EAL_PERSISTENT_MEM_COUNT];
ERROR: "foo* bar" should be "foo *bar"
#302: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:44:
+static void* reserve_shared_zone(int subindex, uint32_t len, int socket_id)
ERROR: do not use C99 // comments
#307: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:49:
+ int shmget_flag = IPC_CREAT | SHM_R | SHM_W | IPC_EXCL; // | SHM_LOCKED;
WARNING: Missing a blank line after declarations
#310: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:52:
+ int err;
+ if((len / RTE_PGSIZE_4K) > 1)
ERROR: that open brace { should be on the previous line
#310: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:52:
+ if((len / RTE_PGSIZE_4K) > 1)
+ {
ERROR: space required before the open parenthesis '('
#310: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:52:
+ if((len / RTE_PGSIZE_4K) > 1)
ERROR: "foo* bar" should be "foo *bar"
#316: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:58:
+ void* addr = 0;
WARNING: Missing a blank line after declarations
#318: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:60:
+ int clear = 1;
+ if(shmid < 0)
ERROR: that open brace { should be on the previous line
#318: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:60:
+ if(shmid < 0)
+ {
ERROR: space required before the open parenthesis '('
#318: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:60:
+ if(shmid < 0)
ERROR: do not use C99 // comments
#320: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:62:
+ //Reuse existing
ERROR: that open brace { should be on the previous line
#328: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:70:
+ if(socket_id != SOCKET_ID_ANY)
+ {
ERROR: space required before the open parenthesis '('
#328: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:70:
+ if(socket_id != SOCKET_ID_ANY)
ERROR: "foo * bar" should be "foo *bar"
#330: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:72:
+ struct bitmask * mask = numa_bitmask_alloc(RTE_MAX_NUMA_NODES);
WARNING: Missing a blank line after declarations
#331: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:73:
+ struct bitmask * mask = numa_bitmask_alloc(RTE_MAX_NUMA_NODES);
+ mask = numa_bitmask_clearall(mask);
ERROR: that open brace { should be on the previous line
#336: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:78:
+ if(ret < 0)
+ {
ERROR: space required before the open parenthesis '('
#336: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:78:
+ if(ret < 0)
ERROR: that open brace { should be on the previous line
#344: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:86:
+ if(clear)
+ {
ERROR: space required before the open parenthesis '('
#344: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:86:
+ if(clear)
WARNING: Missing a blank line after declarations
#350: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:92:
+ size_t size;
+ volatile uint8_t reader = 0; //this prevents from being optimized out
ERROR: do not use C99 // comments
#350: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:92:
+ volatile uint8_t reader = 0; //this prevents from being optimized out
WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
#350: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:92:
+ volatile uint8_t reader = 0; //this prevents from being optimized out
ERROR: "(foo*)" should be "(foo *)"
#351: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:93:
+ volatile uint8_t* readp = (uint8_t*)addr;
ERROR: "foo* bar" should be "foo *bar"
#351: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:93:
+ volatile uint8_t* readp = (uint8_t*)addr;
WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
#351: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:93:
+ volatile uint8_t* readp = (uint8_t*)addr;
WARNING: Missing a blank line after declarations
#352: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:94:
+ volatile uint8_t* readp = (uint8_t*)addr;
+ for(size = 0; size < len; size++)
ERROR: that open brace { should be on the previous line
#352: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:94:
+ for(size = 0; size < len; size++)
+ {
ERROR: space required before the open parenthesis '('
#352: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:94:
+ for(size = 0; size < len; size++)
ERROR: "foo* bar" should be "foo *bar"
#364: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:106:
+void* persistent_allocated_memory[RTE_MAX_NUMA_NODES][SHM_COUNT];
ERROR: do not initialise statics to 0 or NULL
#366: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:108:
+static int numa_count = 0;
ERROR: do not use C99 // comments
#375: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:117:
+ assert(SHM_SIZE == RTE_PGSIZE_2M); //XXX considering only 2MB pages.
WARNING: Missing a blank line after declarations
#377: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:119:
+ int num_numa = numa_num_configured_nodes();
+ if(num_numa == 0)
ERROR: space required before the open parenthesis '('
#377: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:119:
+ if(num_numa == 0)
WARNING: Missing a blank line after declarations
#382: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:124:
+ int k;
+ for(node = 0; node < RTE_MAX_NUMA_NODES; node++)
ERROR: space required before the open parenthesis '('
#382: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:124:
+ for(node = 0; node < RTE_MAX_NUMA_NODES; node++)
ERROR: spaces required around that '=' (ctx:VxV)
#383: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:125:
+ for(k=0; k<SHM_COUNT; k++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#383: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:125:
+ for(k=0; k<SHM_COUNT; k++)
^
ERROR: space required before the open parenthesis '('
#383: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:125:
+ for(k=0; k<SHM_COUNT; k++)
ERROR: that open brace { should be on the previous line
#386: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:128:
+ for(node = 0; node < num_numa; node++)
+ {
ERROR: space required before the open parenthesis '('
#386: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:128:
+ for(node = 0; node < num_numa; node++)
WARNING: Missing a blank line after declarations
#389: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:131:
+ int cur_socket = num_numa > 1 ? node : SOCKET_ID_ANY;
+ for(k=0; k<SHM_COUNT/num_numa; k++)
ERROR: that open brace { should be on the previous line
#389: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:131:
+ for(k=0; k<SHM_COUNT/num_numa; k++)
+ {
ERROR: spaces required around that '=' (ctx:VxV)
#389: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:131:
+ for(k=0; k<SHM_COUNT/num_numa; k++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#389: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:131:
+ for(k=0; k<SHM_COUNT/num_numa; k++)
^
ERROR: space required before the open parenthesis '('
#389: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:131:
+ for(k=0; k<SHM_COUNT/num_numa; k++)
WARNING: Missing a blank line after declarations
#392: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:134:
+ int zone_index = ((SHM_COUNT/num_numa)*node + k);
+ persistent_allocated_memory[node][k] = reserve_shared_zone(zone_index,
ERROR: that open brace { should be on the previous line
#394: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:136:
+ if(persistent_allocated_memory[node][k] == 0)
+ {
ERROR: space required before the open parenthesis '('
#394: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:136:
+ if(persistent_allocated_memory[node][k] == 0)
WARNING: quoted string split across lines
#397: FILE: lib/librte_eal/linuxapp/eal/eal_persistent_mem.c:139:
+ RTE_LOG(ERR, EAL, "Cannot allocate shared zone index %d."
+ "node: %d, local index: %d\n", zone_index, node, k);
ERROR: do not initialise statics to 0 or NULL
#533: FILE: lib/librte_persistent/rte_persistent.c:26:
+static struct rte_hash* allocated_segments = 0;
ERROR: "foo* bar" should be "foo *bar"
#533: FILE: lib/librte_persistent/rte_persistent.c:26:
+static struct rte_hash* allocated_segments = 0;
ERROR: open brace '{' following struct go on the same line
#536: FILE: lib/librte_persistent/rte_persistent.c:29:
+struct alloc_info
+{
ERROR: do not use C99 // comments
#537: FILE: lib/librte_persistent/rte_persistent.c:30:
+ void* addr; //0 if not allocated
ERROR: "foo* bar" should be "foo *bar"
#537: FILE: lib/librte_persistent/rte_persistent.c:30:
+ void* addr; //0 if not allocated
ERROR: do not initialise statics to 0 or NULL
#550: FILE: lib/librte_persistent/rte_persistent.c:43:
+static int __initialized = 0;
ERROR: that open brace { should be on the previous line
#554: FILE: lib/librte_persistent/rte_persistent.c:47:
+ if(!__initialized)
+ {
ERROR: space required before the open parenthesis '('
#554: FILE: lib/librte_persistent/rte_persistent.c:47:
+ if(!__initialized)
ERROR: that open brace { should be on the previous line
#557: FILE: lib/librte_persistent/rte_persistent.c:50:
+ struct rte_hash_parameters hash_param =
+ {
ERROR: "(foo*)" should be "(foo *)"
#561: FILE: lib/librte_persistent/rte_persistent.c:54:
+ .key_len = sizeof(void*),
ERROR: do not use C99 // comments
#562: FILE: lib/librte_persistent/rte_persistent.c:55:
+ .hash_func = 0, //DEFAULT_HASH_FUNC,
WARNING: Missing a blank line after declarations
#571: FILE: lib/librte_persistent/rte_persistent.c:64:
+ int k;
+ for(k=0; k<SEGMENT_COUNT; k++)
ERROR: spaces required around that '=' (ctx:VxV)
#571: FILE: lib/librte_persistent/rte_persistent.c:64:
+ for(k=0; k<SEGMENT_COUNT; k++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#571: FILE: lib/librte_persistent/rte_persistent.c:64:
+ for(k=0; k<SEGMENT_COUNT; k++)
^
ERROR: space required before the open parenthesis '('
#571: FILE: lib/librte_persistent/rte_persistent.c:64:
+ for(k=0; k<SEGMENT_COUNT; k++)
ERROR: "foo* bar" should be "foo *bar"
#588: FILE: lib/librte_persistent/rte_persistent.c:81:
+void* rte_persistent_alloc(size_t size, int socket)
WARNING: Missing a blank line after declarations
#591: FILE: lib/librte_persistent/rte_persistent.c:84:
+ int num_numa = rte_persistent_memory_num_numa();
+ if(socket == SOCKET_ID_ANY)
ERROR: that open brace { should be on the previous line
#591: FILE: lib/librte_persistent/rte_persistent.c:84:
+ if(socket == SOCKET_ID_ANY)
+ {
ERROR: space required before the open parenthesis '('
#591: FILE: lib/librte_persistent/rte_persistent.c:84:
+ if(socket == SOCKET_ID_ANY)
WARNING: Missing a blank line after declarations
#600: FILE: lib/librte_persistent/rte_persistent.c:93:
+ int num_page = (size / ALLOC_UNIT);
+ if(size % ALLOC_UNIT)
ERROR: space required before the open parenthesis '('
#600: FILE: lib/librte_persistent/rte_persistent.c:93:
+ if(size % ALLOC_UNIT)
WARNING: Missing a blank line after declarations
#605: FILE: lib/librte_persistent/rte_persistent.c:98:
+ int k;
+ for(k=0; k<num_page; k++)
ERROR: that open brace { should be on the previous line
#605: FILE: lib/librte_persistent/rte_persistent.c:98:
+ for(k=0; k<num_page; k++)
+ {
ERROR: spaces required around that '=' (ctx:VxV)
#605: FILE: lib/librte_persistent/rte_persistent.c:98:
+ for(k=0; k<num_page; k++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#605: FILE: lib/librte_persistent/rte_persistent.c:98:
+ for(k=0; k<num_page; k++)
^
ERROR: space required before the open parenthesis '('
#605: FILE: lib/librte_persistent/rte_persistent.c:98:
+ for(k=0; k<num_page; k++)
ERROR: "foo* bar" should be "foo *bar"
#611: FILE: lib/librte_persistent/rte_persistent.c:104:
+ void* found_buffer = 0;
WARNING: Missing a blank line after declarations
#612: FILE: lib/librte_persistent/rte_persistent.c:105:
+ void* found_buffer = 0;
+ for(k=l_start; k<(l_start + l_range); k++)
ERROR: that open brace { should be on the previous line
#612: FILE: lib/librte_persistent/rte_persistent.c:105:
+ for(k=l_start; k<(l_start + l_range); k++)
+ {
ERROR: spaces required around that '=' (ctx:VxV)
#612: FILE: lib/librte_persistent/rte_persistent.c:105:
+ for(k=l_start; k<(l_start + l_range); k++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#612: FILE: lib/librte_persistent/rte_persistent.c:105:
+ for(k=l_start; k<(l_start + l_range); k++)
^
ERROR: space required before the open parenthesis '('
#612: FILE: lib/librte_persistent/rte_persistent.c:105:
+ for(k=l_start; k<(l_start + l_range); k++)
ERROR: "foo* bar" should be "foo *bar"
#614: FILE: lib/librte_persistent/rte_persistent.c:107:
+ char* start = alloc_array[k];
ERROR: "foo* bar" should be "foo *bar"
#615: FILE: lib/librte_persistent/rte_persistent.c:108:
+ char* found = strstr(start, find_str);
ERROR: that open brace { should be on the previous line
#617: FILE: lib/librte_persistent/rte_persistent.c:110:
+ if(found)
+ {
ERROR: space required before the open parenthesis '('
#617: FILE: lib/librte_persistent/rte_persistent.c:110:
+ if(found)
WARNING: Missing a blank line after declarations
#620: FILE: lib/librte_persistent/rte_persistent.c:113:
+ int offset = found - start;
+ found_buffer = persistent_allocated_memory[socket][k];
WARNING: Missing a blank line after declarations
#624: FILE: lib/librte_persistent/rte_persistent.c:117:
+ int j;
+ for(j=0; j<num_page; j++)
ERROR: that open brace { should be on the previous line
#624: FILE: lib/librte_persistent/rte_persistent.c:117:
+ for(j=0; j<num_page; j++)
+ {
ERROR: spaces required around that '=' (ctx:VxV)
#624: FILE: lib/librte_persistent/rte_persistent.c:117:
+ for(j=0; j<num_page; j++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#624: FILE: lib/librte_persistent/rte_persistent.c:117:
+ for(j=0; j<num_page; j++)
^
ERROR: space required before the open parenthesis '('
#624: FILE: lib/librte_persistent/rte_persistent.c:117:
+ for(j=0; j<num_page; j++)
WARNING: Missing a blank line after declarations
#629: FILE: lib/librte_persistent/rte_persistent.c:122:
+ int index = rte_hash_add_key(allocated_segments, &found_buffer);
+ assert(index >= 0);
ERROR: "foo* bar" should be "foo *bar"
#639: FILE: lib/librte_persistent/rte_persistent.c:132:
+ void* user = found_buffer;
WARNING: Missing a blank line after declarations
#642: FILE: lib/librte_persistent/rte_persistent.c:135:
+ size_t diff = RTE_MAX((uint64_t)user, hw) - RTE_MIN((uint64_t)user, hw);
+ for(j = 0; j < num_page; j++)
ERROR: that open brace { should be on the previous line
#642: FILE: lib/librte_persistent/rte_persistent.c:135:
+ for(j = 0; j < num_page; j++)
+ {
ERROR: space required before the open parenthesis '('
#642: FILE: lib/librte_persistent/rte_persistent.c:135:
+ for(j = 0; j < num_page; j++)
ERROR: "(foo*)" should be "(foo *)"
#645: FILE: lib/librte_persistent/rte_persistent.c:138:
+ void* cur_user = ((char*)user + shift);
ERROR: "foo* bar" should be "foo *bar"
#645: FILE: lib/librte_persistent/rte_persistent.c:138:
+ void* cur_user = ((char*)user + shift);
WARNING: line over 120 characters
#647: FILE: lib/librte_persistent/rte_persistent.c:140:
+ size_t cur_diff = RTE_MAX((uint64_t)cur_user, cur_hw) - RTE_MIN((uint64_t)cur_user, cur_hw);
ERROR: that open brace { should be on the previous line
#649: FILE: lib/librte_persistent/rte_persistent.c:142:
+ if(cur_diff != diff)
+ {
ERROR: space required before the open parenthesis '('
#649: FILE: lib/librte_persistent/rte_persistent.c:142:
+ if(cur_diff != diff)
WARNING: line over 120 characters
#651: FILE: lib/librte_persistent/rte_persistent.c:144:
+ RTE_LOG(ERR, EAL, "Hugepage is not contiguous, curdiff: %lX, expected: %lX\n", cur_diff, diff);
ERROR: space required before the open parenthesis '('
#658: FILE: lib/librte_persistent/rte_persistent.c:151:
+ if(!found_buffer)
ERROR: "foo* bar" should be "foo *bar"
#663: FILE: lib/librte_persistent/rte_persistent.c:156:
+phys_addr_t rte_persistent_hw_addr(const void* addr)
ERROR: space required before the open parenthesis '('
#665: FILE: lib/librte_persistent/rte_persistent.c:158:
+ if(addr == 0)
ERROR: "(foo*)" should be "(foo *)"
#667: FILE: lib/librte_persistent/rte_persistent.c:160:
+ int index = rte_hash_lookup(allocated_segments, (const void*)&addr);
WARNING: Missing a blank line after declarations
#668: FILE: lib/librte_persistent/rte_persistent.c:161:
+ int index = rte_hash_lookup(allocated_segments, (const void*)&addr);
+ assert(index >= 0);
ERROR: "foo* bar" should be "foo *bar"
#674: FILE: lib/librte_persistent/rte_persistent.c:167:
+size_t rte_persistent_mem_length(const void* addr)
ERROR: "(foo*)" should be "(foo *)"
#676: FILE: lib/librte_persistent/rte_persistent.c:169:
+ int index = rte_hash_lookup(allocated_segments, (const void*)&addr);
WARNING: Missing a blank line after declarations
#677: FILE: lib/librte_persistent/rte_persistent.c:170:
+ int index = rte_hash_lookup(allocated_segments, (const void*)&addr);
+ assert(index >= 0);
ERROR: "foo* bar" should be "foo *bar"
#683: FILE: lib/librte_persistent/rte_persistent.c:176:
+void rte_persistent_free(void* addr)
ERROR: "(foo*)" should be "(foo *)"
#685: FILE: lib/librte_persistent/rte_persistent.c:178:
+ int index = rte_hash_lookup(allocated_segments, (const void*)&addr);
WARNING: Missing a blank line after declarations
#686: FILE: lib/librte_persistent/rte_persistent.c:179:
+ int index = rte_hash_lookup(allocated_segments, (const void*)&addr);
+ assert(index >= 0);
ERROR: "(foo*)" should be "(foo *)"
#700: FILE: lib/librte_persistent/rte_persistent.c:193:
+ rte_hash_del_key(allocated_segments, (const void*)&addr);
WARNING: Missing a blank line after declarations
#703: FILE: lib/librte_persistent/rte_persistent.c:196:
+ int k;
+ for(k=0; k<len; k++)
ERROR: spaces required around that '=' (ctx:VxV)
#703: FILE: lib/librte_persistent/rte_persistent.c:196:
+ for(k=0; k<len; k++)
^
ERROR: spaces required around that '<' (ctx:VxV)
#703: FILE: lib/librte_persistent/rte_persistent.c:196:
+ for(k=0; k<len; k++)
^
ERROR: space required before the open parenthesis '('
#703: FILE: lib/librte_persistent/rte_persistent.c:196:
+ for(k=0; k<len; k++)
ERROR: "foo* bar" should be "foo *bar"
#726: FILE: lib/librte_persistent/rte_persistent.h:15:
+void* rte_persistent_alloc(size_t size, int socket);
ERROR: "foo* bar" should be "foo *bar"
#727: FILE: lib/librte_persistent/rte_persistent.h:16:
+phys_addr_t rte_persistent_hw_addr(const void* addr);
ERROR: "foo* bar" should be "foo *bar"
#728: FILE: lib/librte_persistent/rte_persistent.h:17:
+void rte_persistent_free(void* addr);
ERROR: "foo* bar" should be "foo *bar"
#729: FILE: lib/librte_persistent/rte_persistent.h:18:
+size_t rte_persistent_mem_length(const void* addr);
total: 96 errors, 28 warnings, 573 lines checked
/tmp/persist.patch has style problems, please review.
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
^ permalink raw reply [relevance 1%]
* Re: [dpdk-dev] [PATCH] mk: enable next abi in static libs
2015-07-06 13:49 8% ` Thomas Monjalon
@ 2015-07-06 18:22 9% ` Neil Horman
2015-07-06 21:44 9% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-07-06 18:22 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Mon, Jul 06, 2015 at 03:49:50PM +0200, Thomas Monjalon wrote:
> 2015-07-06 09:35, Neil Horman:
> > On Mon, Jul 06, 2015 at 03:18:51PM +0200, Thomas Monjalon wrote:
> > > Any comment or ack?
> > >
> > > 2015-07-03 00:05, Thomas Monjalon:
> > > > When a change makes really hard to keep ABI compatibility,
> > > > instead of waiting next release to break the ABI, it is smoother
> > > > to introduce the new code and enable it only for static libraries.
> > > > The flag RTE_NEXT_ABI may be used to "ifdef" the new code.
> > > > When the release is out, a dynamically linked application can use
> > > > the new shared libraries without rebuild while developpers can prepare
> > > > their application for the next ABI by reading the deprecation notice
> > > > and easily testing the new code.
> > > > When starting the next release cycle, the "ifdefs" will be removed
> > > > and the ABI break will be marked by incrementing LIBABIVER.
> > > >
> > > > The new option CONFIG_RTE_NEXT_ABI is not defined in the configuration
> > > > templates because it is deduced from CONFIG_RTE_BUILD_SHARED_LIB.
> > > > It is automatically enabled for static libraries and disabled for
> > > > shared libraries.
> > > > It can be forced to another value by editing the generated .config file.
> > > > It shouldn't be enabled for shared libraries because it would break the
> > > > ABI without changing the version number LIBABIVER. That's why a warning
> > > > is printed in this case.
> > > >
> > > > The guideline is also updated to integrate this new possibility.
> > > >
> > > > Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
> > >
> > >
> > Yeah, I'm not sure why this is necessecary. That is to say, if you want to
>
> It's explained at the beginning:
> "When a change makes really hard to keep ABI compatibility", e.g. mbuf change.
>
Thats not what I was referring to. I was referring to the need to split out
ABI's based on a separate config item only for static libraries. I understand
that sometimes you want a 'preview' of the next abi.
> > introduce a new ABI operation prior to the old one being removed, that is precisely what
> > the versioning macros are for, and can be used to map the static api to the new
> > version. e.g, given function X that you want to enhance in an ABI breaking way:
> >
> > 1) Separate function X to X_v1 and X_v2
> > 2) Map X_v2 to X@DPDK_v2, map X_v1 to X@DPDK_v1
> > 3) Map the static symbol X to X_v2
> > 4) Post the deprecation notice of X for release 3 immediately
>
> We cannot do that for mbuf change.
>
You can actually, its just alot of work. Also, I know this doesn't relate very
closely to the subject, and I apologize, I was really just reacting to the
immediately preceding sentence in the origional post.
> > Splitting the static ABI from the shared ABI just means that applications will
> > have the opportunity to isolate themselves to one kind of build, which is a bad
> > idea.
>
> It helps to be prepared for the next release by testing the app with static libraries.
> We agreed to allow API breaking for important changes like mbuf rework.
> This option NEXT_ABI is a step between announcement and effective ABI breaking.
>
> I think it's a reasonnable approach. But if nobody ack it, I'm perfectly OK to
> drop it and related features (unified packet type and interrupt mode).
>
I'd be ok with it iff:
1) It applies to static and shared ABI's together. That is to say that setting
the NEXT_ABI config flag creates the same ABI changes regardless of other build
configuration. It needs to be used in such a way that a consistent ABI is
presented when set, otherwise it won't be useful.
2) It only applies to the next ABI. That is to say, it can't be a hodgepodge of
the next ABI and the one after that, and the one after that, or it won't provide
an appropriate preview for anyone.
If we can meet those two standards, it would likely be a useful feature to have.
Neil
>
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [PATCH 4/4] ethdev: check support for rx_queue_count and descriptor_done fns
@ 2015-07-06 15:11 3% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-07-06 15:11 UTC (permalink / raw)
To: nhorman; +Cc: dev
Neil, your ABI expertise is required for this patch.
2015-06-15 11:14, Bruce Richardson:
> On Fri, Jun 12, 2015 at 01:32:56PM -0400, Roger B. Melton wrote:
> > Hi Bruce, Comment in-line. Regards, Roger
> >
> > On 6/12/15 7:28 AM, Bruce Richardson wrote:
> > >The functions rte_eth_rx_queue_count and rte_eth_descriptor_done are
> > >supported by very few PMDs. Therefore, it is best to check for support
> > >for the functions in the ethdev library, so as to avoid crashes
> > >at run-time if the application goes to use those APIs. The performance
> > >impact of this change should be very small as this is a predictable
> > >branch in the function.
> > >
> > >Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > >---
> > > lib/librte_ether/rte_ethdev.h | 8 ++++++--
> > > 1 file changed, 6 insertions(+), 2 deletions(-)
> > >
> > >diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> > >index 827ca3e..9ad1b6a 100644
> > >--- a/lib/librte_ether/rte_ethdev.h
> > >+++ b/lib/librte_ether/rte_ethdev.h
> > >@@ -2496,6 +2496,8 @@ rte_eth_rx_burst(uint8_t port_id, uint16_t queue_id,
> > > * The queue id on the specific port.
> > > * @return
> > > * The number of used descriptors in the specific queue.
> > >+ * NOTE: if function is not supported by device this call
> > >+ * returns (uint32_t)-ENOTSUP
> > > */
> > > static inline uint32_t
> >
> > Why not change the return type to int32_t?
> > In this way, the caller isn't required to make the assumption that a large
> > queue count indicates an error. < 0 means error, other wise it's a valid
> > queue count.
> >
> > This approach would be consistent with other APIs.
> >
>
> Yes, good point, I should see about that. One thing I'm unsure of, though, is
> does this count as ABI breakage? I don't see how it should break any older
> apps, since the return type is the same size, but I'm not sure as we are
> changing the return type of the function.
>
> Neil, can you perhaps comment here? Is changing uint32_t to int32_t ok, from
> an ABI point of view?
>
> Regards,
> /Bruce
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v2] doc: fix minor sphinx build warning
2015-07-02 14:15 8% [dpdk-dev] [PATCH v2] doc: fix minor sphinx build warning John McNamara
@ 2015-07-06 14:55 0% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-07-06 14:55 UTC (permalink / raw)
To: John McNamara; +Cc: dev
2015-07-02 15:15, John McNamara:
> Fix for a minor Sphinx build warning in the ABI guidelines docs:
>
> versioning.rst:126: WARNING: Bullet list ends without a
> blank line; unexpected unindent.
>
> Signed-off-by: John McNamara <john.mcnamara@intel.com>
Applied, thanks
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH] mk: enable next abi in static libs
2015-07-06 13:35 9% ` Neil Horman
@ 2015-07-06 13:49 8% ` Thomas Monjalon
2015-07-06 18:22 9% ` Neil Horman
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-07-06 13:49 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-07-06 09:35, Neil Horman:
> On Mon, Jul 06, 2015 at 03:18:51PM +0200, Thomas Monjalon wrote:
> > Any comment or ack?
> >
> > 2015-07-03 00:05, Thomas Monjalon:
> > > When a change makes really hard to keep ABI compatibility,
> > > instead of waiting next release to break the ABI, it is smoother
> > > to introduce the new code and enable it only for static libraries.
> > > The flag RTE_NEXT_ABI may be used to "ifdef" the new code.
> > > When the release is out, a dynamically linked application can use
> > > the new shared libraries without rebuild while developpers can prepare
> > > their application for the next ABI by reading the deprecation notice
> > > and easily testing the new code.
> > > When starting the next release cycle, the "ifdefs" will be removed
> > > and the ABI break will be marked by incrementing LIBABIVER.
> > >
> > > The new option CONFIG_RTE_NEXT_ABI is not defined in the configuration
> > > templates because it is deduced from CONFIG_RTE_BUILD_SHARED_LIB.
> > > It is automatically enabled for static libraries and disabled for
> > > shared libraries.
> > > It can be forced to another value by editing the generated .config file.
> > > It shouldn't be enabled for shared libraries because it would break the
> > > ABI without changing the version number LIBABIVER. That's why a warning
> > > is printed in this case.
> > >
> > > The guideline is also updated to integrate this new possibility.
> > >
> > > Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
> >
> >
> Yeah, I'm not sure why this is necessecary. That is to say, if you want to
It's explained at the beginning:
"When a change makes really hard to keep ABI compatibility", e.g. mbuf change.
> introduce a new ABI operation prior to the old one being removed, that is precisely what
> the versioning macros are for, and can be used to map the static api to the new
> version. e.g, given function X that you want to enhance in an ABI breaking way:
>
> 1) Separate function X to X_v1 and X_v2
> 2) Map X_v2 to X@DPDK_v2, map X_v1 to X@DPDK_v1
> 3) Map the static symbol X to X_v2
> 4) Post the deprecation notice of X for release 3 immediately
We cannot do that for mbuf change.
> Splitting the static ABI from the shared ABI just means that applications will
> have the opportunity to isolate themselves to one kind of build, which is a bad
> idea.
It helps to be prepared for the next release by testing the app with static libraries.
We agreed to allow API breaking for important changes like mbuf rework.
This option NEXT_ABI is a step between announcement and effective ABI breaking.
I think it's a reasonnable approach. But if nobody ack it, I'm perfectly OK to
drop it and related features (unified packet type and interrupt mode).
^ permalink raw reply [relevance 8%]
* Re: [dpdk-dev] [PATCH] mk: enable next abi in static libs
2015-07-06 13:18 4% ` Thomas Monjalon
@ 2015-07-06 13:35 9% ` Neil Horman
2015-07-06 13:49 8% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-07-06 13:35 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Mon, Jul 06, 2015 at 03:18:51PM +0200, Thomas Monjalon wrote:
> Any comment or ack?
>
> 2015-07-03 00:05, Thomas Monjalon:
> > When a change makes really hard to keep ABI compatibility,
> > instead of waiting next release to break the ABI, it is smoother
> > to introduce the new code and enable it only for static libraries.
> > The flag RTE_NEXT_ABI may be used to "ifdef" the new code.
> > When the release is out, a dynamically linked application can use
> > the new shared libraries without rebuild while developpers can prepare
> > their application for the next ABI by reading the deprecation notice
> > and easily testing the new code.
> > When starting the next release cycle, the "ifdefs" will be removed
> > and the ABI break will be marked by incrementing LIBABIVER.
> >
> > The new option CONFIG_RTE_NEXT_ABI is not defined in the configuration
> > templates because it is deduced from CONFIG_RTE_BUILD_SHARED_LIB.
> > It is automatically enabled for static libraries and disabled for
> > shared libraries.
> > It can be forced to another value by editing the generated .config file.
> > It shouldn't be enabled for shared libraries because it would break the
> > ABI without changing the version number LIBABIVER. That's why a warning
> > is printed in this case.
> >
> > The guideline is also updated to integrate this new possibility.
> >
> > Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
>
>
Yeah, I'm not sure why this is necessecary. That is to say, if you want to
introduce a new ABI operation prior to the old one being removed, that is precisely what
the versioning macros are for, and can be used to map the static api to the new
version. e.g, given function X that you want to enhance in an ABI breaking way:
1) Separate function X to X_v1 and X_v2
2) Map X_v2 to X@DPDK_v2, map X_v1 to X@DPDK_v1
3) Map the static symbol X to X_v2
4) Post the deprecation notice of X for release 3 immediately
Splitting the static ABI from the shared ABI just means that applications will
have the opportunity to isolate themselves to one kind of build, which is a bad
idea.
Neil
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [PATCH] mk: enable next abi in static libs
2015-07-02 22:05 20% [dpdk-dev] [PATCH] mk: enable next abi in static libs Thomas Monjalon
@ 2015-07-06 13:18 4% ` Thomas Monjalon
2015-07-06 13:35 9% ` Neil Horman
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-07-06 13:18 UTC (permalink / raw)
To: dev
Any comment or ack?
2015-07-03 00:05, Thomas Monjalon:
> When a change makes really hard to keep ABI compatibility,
> instead of waiting next release to break the ABI, it is smoother
> to introduce the new code and enable it only for static libraries.
> The flag RTE_NEXT_ABI may be used to "ifdef" the new code.
> When the release is out, a dynamically linked application can use
> the new shared libraries without rebuild while developpers can prepare
> their application for the next ABI by reading the deprecation notice
> and easily testing the new code.
> When starting the next release cycle, the "ifdefs" will be removed
> and the ABI break will be marked by incrementing LIBABIVER.
>
> The new option CONFIG_RTE_NEXT_ABI is not defined in the configuration
> templates because it is deduced from CONFIG_RTE_BUILD_SHARED_LIB.
> It is automatically enabled for static libraries and disabled for
> shared libraries.
> It can be forced to another value by editing the generated .config file.
> It shouldn't be enabled for shared libraries because it would break the
> ABI without changing the version number LIBABIVER. That's why a warning
> is printed in this case.
>
> The guideline is also updated to integrate this new possibility.
>
> Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v3 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2
2015-07-02 15:16 14% ` [dpdk-dev] [PATCH v3 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
@ 2015-07-06 13:16 4% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-07-06 13:16 UTC (permalink / raw)
To: dev, nhorman
2015-07-02 16:16, John McNamara:
> --- a/doc/guides/rel_notes/abi.rst
> +++ b/doc/guides/rel_notes/abi.rst
> Deprecation Notices
> -------------------
> +
> +* In DPDK 2.1 the IEEE1588/802.1AS support in the i40e driver makes use of the
> + ``udata64`` field in the mbuf to pass the timesync register index to the
> + user. In DPDK 2.2 this will be moved to a new field in the mbuf.
We need more acknowledgements for this decision, as stated here:
http://dpdk.org/browse/dpdk/tree/doc/guides/guidelines/versioning.rst#n51
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v4 1/4] ethdev: rename rte_eth_vmdq_mirror_conf
2015-06-26 7:03 5% ` Wu, Jingjing
@ 2015-07-06 1:27 0% ` Wu, Jingjing
0 siblings, 0 replies; 200+ results
From: Wu, Jingjing @ 2015-07-06 1:27 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
Hi, Thomas
Any suggestions about this patch? Do I need rework it by using macro RTE_NEXT_ABI?
Thanks a lot!
Jingjing
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wu, Jingjing
> Sent: Friday, June 26, 2015 3:03 PM
> To: 'nhorman@tuxdriver.com'
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v4 1/4] ethdev: rename
> rte_eth_vmdq_mirror_conf
>
> Hi, Neil
>
> About this patch I have an ABI concern about it.
> This patch just renamed a struct rte_eth_vmdq_mirror_conf to
> rte_eth_mirror_conf, the size and its elements don't change. As my
> understanding, it will not break the ABI. And I also tested it.
> But when I use the script ./scripts/validate-abi.sh to check. A low severity
> problem is reported in symbol "rte_eth_mirror_rule_set"
> - Change: "Base type of 2nd parameter mirror_conf has been changed from
> struct rte_eth_vmdq_mirror_conf to struct rte_eth_mirror_conf."
> - Effect: "Replacement of parameter base type may indicate a change in its
> semantic meaning."
>
> So, I'm not sure whether this patch meet the ABI policy?
>
> Additional, about the validate-abi.sh, does it mean we need to fix all the
> problems it reports? Or we can decide case by case. Can a Low Severity
> problem be acceptable?
>
> Look forward to your reply.
>
> Thanks
>
> Jingjing
>
> > -----Original Message-----
> > From: Wu, Jingjing
> > Sent: Wednesday, June 10, 2015 2:25 PM
> > To: dev@dpdk.org
> > Cc: Wu, Jingjing; Liu, Jijiang; Jiajia, SunX; Zhang, Helin
> > Subject: [PATCH v4 1/4] ethdev: rename rte_eth_vmdq_mirror_conf
> >
> > rename rte_eth_vmdq_mirror_conf to rte_eth_mirror_conf and move the
> > maximum rule id check from ethdev level to driver
> >
> > Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
> > ---
> > app/test-pmd/cmdline.c | 22 +++++++++++-----------
> > drivers/net/ixgbe/ixgbe_ethdev.c | 11 +++++++----
> > drivers/net/ixgbe/ixgbe_ethdev.h | 4 +++-
> > lib/librte_ether/rte_ethdev.c | 18 ++----------------
> > lib/librte_ether/rte_ethdev.h | 19 ++++++++++---------
> > 5 files changed, 33 insertions(+), 41 deletions(-)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > f01db2a..d693bde 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -6604,11 +6604,11 @@ cmd_set_mirror_mask_parsed(void
> > *parsed_result, {
> > int ret,nb_item,i;
> > struct cmd_set_mirror_mask_result *res = parsed_result;
> > - struct rte_eth_vmdq_mirror_conf mr_conf;
> > + struct rte_eth_mirror_conf mr_conf;
> >
> > - memset(&mr_conf,0,sizeof(struct rte_eth_vmdq_mirror_conf));
> > + memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
> >
> > - unsigned int vlan_list[ETH_VMDQ_MAX_VLAN_FILTERS];
> > + unsigned int vlan_list[ETH_MIRROR_MAX_VLANS];
> >
> > mr_conf.dst_pool = res->dstpool_id;
> >
> > @@ -6618,11 +6618,11 @@ cmd_set_mirror_mask_parsed(void
> > *parsed_result,
> > } else if(!strcmp(res->what, "vlan-mirror")) {
> > mr_conf.rule_type_mask = ETH_VMDQ_VLAN_MIRROR;
> > nb_item = parse_item_list(res->value, "core",
> > -
> > ETH_VMDQ_MAX_VLAN_FILTERS,vlan_list,1);
> > + ETH_MIRROR_MAX_VLANS, vlan_list,
> > 1);
> > if (nb_item <= 0)
> > return;
> >
> > - for(i=0; i < nb_item; i++) {
> > + for (i = 0; i < nb_item; i++) {
> > if (vlan_list[i] > ETHER_MAX_VLAN_ID) {
> > printf("Invalid vlan_id: must be < 4096\n");
> > return;
> > @@ -6634,10 +6634,10 @@ cmd_set_mirror_mask_parsed(void
> > *parsed_result,
> > }
> >
> > if(!strcmp(res->on, "on"))
> > - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> > + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> > res->rule_id, 1);
> > else
> > - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> > + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> > res->rule_id, 0);
> > if(ret < 0)
> > printf("mirror rule add error: (%s)\n", strerror(-ret)); @@ -
> > 6711,9 +6711,9 @@ cmd_set_mirror_link_parsed(void *parsed_result, {
> > int ret;
> > struct cmd_set_mirror_link_result *res = parsed_result;
> > - struct rte_eth_vmdq_mirror_conf mr_conf;
> > + struct rte_eth_mirror_conf mr_conf;
> >
> > - memset(&mr_conf,0,sizeof(struct rte_eth_vmdq_mirror_conf));
> > + memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
> > if(!strcmp(res->what, "uplink-mirror")) {
> > mr_conf.rule_type_mask = ETH_VMDQ_UPLINK_MIRROR;
> > }else if(!strcmp(res->what, "downlink-mirror")) @@ -6722,10
> > +6722,10 @@ cmd_set_mirror_link_parsed(void *parsed_result,
> > mr_conf.dst_pool = res->dstpool_id;
> >
> > if(!strcmp(res->on, "on"))
> > - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> > + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> > res->rule_id, 1);
> > else
> > - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> > + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> > res->rule_id, 0);
> >
> > /* check the return value and print it if is < 0 */ diff --git
> > a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index 0d9f9b2..9e767fa 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > @@ -209,7 +209,7 @@ static int ixgbe_set_pool_tx(struct rte_eth_dev
> > *dev,uint16_t pool,uint8_t on); static int
> > ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
> > uint64_t pool_mask,uint8_t vlan_on); static int
> > ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
> > - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> > + struct rte_eth_mirror_conf *mirror_conf,
> > uint8_t rule_id, uint8_t on);
> > static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev,
> > uint8_t rule_id);
> > @@ -3388,7 +3388,7 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev
> > *dev, uint16_t vlan,
> >
> > static int
> > ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
> > - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> > + struct rte_eth_mirror_conf *mirror_conf,
> > uint8_t rule_id, uint8_t on)
> > {
> > uint32_t mr_ctl,vlvf;
> > @@ -3412,7 +3412,10 @@ ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
> > IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> >
> > if (ixgbe_vmdq_mode_check(hw) < 0)
> > - return (-ENOTSUP);
> > + return -ENOTSUP;
> > +
> > + if (rule_id >= IXGBE_MAX_MIRROR_RULES)
> > + return -EINVAL;
> >
> > /* Check if vlan mask is valid */
> > if ((mirror_conf->rule_type_mask & ETH_VMDQ_VLAN_MIRROR)
> && (on)) {
> > @@ -3526,7 +3529,7 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev
> *dev,
> > uint8_t rule_id)
> > return (-ENOTSUP);
> >
> > memset(&mr_info->mr_conf[rule_id], 0,
> > - sizeof(struct rte_eth_vmdq_mirror_conf));
> > + sizeof(struct rte_eth_mirror_conf));
> >
> > /* clear PFVMCTL register */
> > IXGBE_WRITE_REG(hw, IXGBE_MRCTL(rule_id), mr_ctl); diff --git
> > a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
> > index 19237b8..755b674 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.h
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.h
> > @@ -177,8 +177,10 @@ struct ixgbe_uta_info {
> > uint32_t uta_shadow[IXGBE_MAX_UTA];
> > };
> >
> > +#define IXGBE_MAX_MIRROR_RULES 4 /* Maximum nb. of mirror rules.
> */
> > +
> > struct ixgbe_mirror_info {
> > - struct rte_eth_vmdq_mirror_conf
> > mr_conf[ETH_VMDQ_NUM_MIRROR_RULE];
> > + struct rte_eth_mirror_conf mr_conf[IXGBE_MAX_MIRROR_RULES];
> > /**< store PF mirror rules configuration*/ };
> >
> > diff --git a/lib/librte_ether/rte_ethdev.c
> > b/lib/librte_ether/rte_ethdev.c index 024fe8b..43c7295 100644
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -3034,7 +3034,7 @@ int rte_eth_set_vf_rate_limit(uint8_t port_id,
> > uint16_t vf, uint16_t tx_rate,
> >
> > int
> > rte_eth_mirror_rule_set(uint8_t port_id,
> > - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> > + struct rte_eth_mirror_conf *mirror_conf,
> > uint8_t rule_id, uint8_t on)
> > {
> > struct rte_eth_dev *dev = &rte_eth_devices[port_id]; @@ -3051,7
> > +3051,7 @@ rte_eth_mirror_rule_set(uint8_t port_id,
> >
> > if (mirror_conf->dst_pool >= ETH_64_POOLS) {
> > PMD_DEBUG_TRACE("Invalid dst pool, pool id must"
> > - "be 0-%d\n",ETH_64_POOLS - 1);
> > + "be 0-%d\n", ETH_64_POOLS - 1);
> > return -EINVAL;
> > }
> >
> > @@ -3062,13 +3062,6 @@ rte_eth_mirror_rule_set(uint8_t port_id,
> > return -EINVAL;
> > }
> >
> > - if(rule_id >= ETH_VMDQ_NUM_MIRROR_RULE)
> > - {
> > - PMD_DEBUG_TRACE("Invalid rule_id, rule_id must be 0-
> > %d\n",
> > - ETH_VMDQ_NUM_MIRROR_RULE - 1);
> > - return -EINVAL;
> > - }
> > -
> > dev = &rte_eth_devices[port_id];
> > FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mirror_rule_set, -
> ENOTSUP);
> >
> > @@ -3085,13 +3078,6 @@ rte_eth_mirror_rule_reset(uint8_t port_id,
> > uint8_t rule_id)
> > return -ENODEV;
> > }
> >
> > - if(rule_id >= ETH_VMDQ_NUM_MIRROR_RULE)
> > - {
> > - PMD_DEBUG_TRACE("Invalid rule_id, rule_id must be 0-
> > %d\n",
> > - ETH_VMDQ_NUM_MIRROR_RULE-1);
> > - return -EINVAL;
> > - }
> > -
> > dev = &rte_eth_devices[port_id];
> > FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mirror_rule_reset, -
> ENOTSUP);
> >
> > diff --git a/lib/librte_ether/rte_ethdev.h
> > b/lib/librte_ether/rte_ethdev.h index 16dbe00..ae22fea 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -467,8 +467,8 @@ struct rte_eth_rss_conf {
> > #define ETH_VMDQ_ACCEPT_BROADCAST 0x0008 /**< accept broadcast
> > packets. */
> > #define ETH_VMDQ_ACCEPT_MULTICAST 0x0010 /**< multicast
> > promiscuous. */
> >
> > -/* Definitions used for VMDQ mirror rules setting */
> > -#define ETH_VMDQ_NUM_MIRROR_RULE 4 /**< Maximum nb. of
> mirror
> > rules. . */
> > +/** Maximum nb. of vlan per mirror rule */
> > +#define ETH_MIRROR_MAX_VLANS 64
> >
> > #define ETH_VMDQ_POOL_MIRROR 0x0001 /**< Virtual Pool Mirroring.
> */
> > #define ETH_VMDQ_UPLINK_MIRROR 0x0002 /**< Uplink Port Mirroring.
> > */ @@ -480,18 +480,19 @@ struct rte_eth_rss_conf {
> > */
> > struct rte_eth_vlan_mirror {
> > uint64_t vlan_mask; /**< mask for valid VLAN ID. */
> > - uint16_t vlan_id[ETH_VMDQ_MAX_VLAN_FILTERS];
> > - /** VLAN ID list for vlan mirror. */
> > + /** VLAN ID list for vlan mirroring. */
> > + uint16_t vlan_id[ETH_MIRROR_MAX_VLANS];
> > };
> >
> > /**
> > * A structure used to configure traffic mirror of an Ethernet port.
> > */
> > -struct rte_eth_vmdq_mirror_conf {
> > +struct rte_eth_mirror_conf {
> > uint8_t rule_type_mask; /**< Mirroring rule type mask we want to
> set
> > */
> > - uint8_t dst_pool; /**< Destination pool for this mirror rule. */
> > + uint8_t dst_pool; /**< Destination pool for this mirror rule. */
> > uint64_t pool_mask; /**< Bitmap of pool for pool mirroring */
> > - struct rte_eth_vlan_mirror vlan; /**< VLAN ID setting for VLAN
> > mirroring */
> > + /** VLAN ID setting for VLAN mirroring. */
> > + struct rte_eth_vlan_mirror vlan;
> > };
> >
> > /**
> > @@ -1211,7 +1212,7 @@ typedef int (*eth_set_vf_rate_limit_t)(struct
> > rte_eth_dev *dev, /**< @internal Set VF TX rate */
> >
> > typedef int (*eth_mirror_rule_set_t)(struct rte_eth_dev *dev,
> > - struct rte_eth_vmdq_mirror_conf
> > *mirror_conf,
> > + struct rte_eth_mirror_conf *mirror_conf,
> > uint8_t rule_id,
> > uint8_t on);
> > /**< @internal Add a traffic mirroring rule on an Ethernet device */
> > @@ -
> > 3168,7 +3169,7 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port,
> > uint16_t vlan_id,
> > * - (-EINVAL) if the mr_conf information is not correct.
> > */
> > int rte_eth_mirror_rule_set(uint8_t port_id,
> > - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> > + struct rte_eth_mirror_conf *mirror_conf,
> > uint8_t rule_id,
> > uint8_t on);
> >
> > --
> > 1.9.3
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH v4 4/8] ethdev: remove HW specific stats in stats structs
2015-07-05 17:39 3% [dpdk-dev] [PATCH v4 0/8] Expose IXGBE extended stats to DPDK apps Maryam Tahhan
@ 2015-07-05 17:39 9% ` Maryam Tahhan
0 siblings, 0 replies; 200+ results
From: Maryam Tahhan @ 2015-07-05 17:39 UTC (permalink / raw)
To: dev
Remove non generic stats in rte_stats_strings and mark the relevant
fields in struct rte_eth_stats as deprecated.
Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
---
doc/guides/rel_notes/abi.rst | 11 +++++++++++
lib/librte_ether/rte_ethdev.c | 9 ---------
lib/librte_ether/rte_ethdev.h | 30 ++++++++++++++++++++----------
3 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index 110c486..90fe7fa 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -12,3 +12,14 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* The following fields have been deprecated in rte_eth_stats:
+ * uint64_t imissed
+ * uint64_t ibadcrc
+ * uint64_t ibadlen
+ * uint64_t imcasts
+ * uint64_t fdirmatch
+ * uint64_t fdirmiss
+ * uint64_t tx_pause_xon
+ * uint64_t rx_pause_xon
+ * uint64_t tx_pause_xoff
+ * uint64_t rx_pause_xoff
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e392f60..003c548 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -142,17 +142,8 @@ static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
{"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
{"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
{"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
- {"rx_missed_errors", offsetof(struct rte_eth_stats, imissed)},
- {"rx_crc_errors", offsetof(struct rte_eth_stats, ibadcrc)},
- {"rx_bad_length_errors", offsetof(struct rte_eth_stats, ibadlen)},
{"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
{"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
- {"fdir_match", offsetof(struct rte_eth_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct rte_eth_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct rte_eth_stats, tx_pause_xon)},
- {"rx_flow_control_xon", offsetof(struct rte_eth_stats, rx_pause_xon)},
- {"tx_flow_control_xoff", offsetof(struct rte_eth_stats, tx_pause_xoff)},
- {"rx_flow_control_xoff", offsetof(struct rte_eth_stats, rx_pause_xoff)},
};
#define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index f1219ac..a38d49a 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -193,19 +193,29 @@ struct rte_eth_stats {
uint64_t opackets; /**< Total number of successfully transmitted packets.*/
uint64_t ibytes; /**< Total number of successfully received bytes. */
uint64_t obytes; /**< Total number of successfully transmitted bytes. */
- uint64_t imissed; /**< Total of RX missed packets (e.g full FIFO). */
- uint64_t ibadcrc; /**< Total of RX packets with CRC error. */
- uint64_t ibadlen; /**< Total of RX packets with bad length. */
+ /**< Deprecated; Total of RX missed packets (e.g full FIFO). */
+ uint64_t imissed;
+ /**< Deprecated; Total of RX packets with CRC error. */
+ uint64_t ibadcrc;
+ /**< Deprecated; Total of RX packets with bad length. */
+ uint64_t ibadlen;
uint64_t ierrors; /**< Total number of erroneous received packets. */
uint64_t oerrors; /**< Total number of failed transmitted packets. */
- uint64_t imcasts; /**< Total number of multicast received packets. */
+ uint64_t imcasts;
+ /**< Deprecated; Total number of multicast received packets. */
uint64_t rx_nombuf; /**< Total number of RX mbuf allocation failures. */
- uint64_t fdirmatch; /**< Total number of RX packets matching a filter. */
- uint64_t fdirmiss; /**< Total number of RX packets not matching any filter. */
- uint64_t tx_pause_xon; /**< Total nb. of XON pause frame sent. */
- uint64_t rx_pause_xon; /**< Total nb. of XON pause frame received. */
- uint64_t tx_pause_xoff; /**< Total nb. of XOFF pause frame sent. */
- uint64_t rx_pause_xoff; /**< Total nb. of XOFF pause frame received. */
+ uint64_t fdirmatch;
+ /**< Deprecated; Total number of RX packets matching a filter. */
+ uint64_t fdirmiss;
+ /**< Deprecated; Total number of RX packets not matching any filter. */
+ uint64_t tx_pause_xon;
+ /**< Deprecated; Total nb. of XON pause frame sent. */
+ uint64_t rx_pause_xon;
+ /**< Deprecated; Total nb. of XON pause frame received. */
+ uint64_t tx_pause_xoff;
+ /**< Deprecated; Total nb. of XOFF pause frame sent. */
+ uint64_t rx_pause_xoff;
+ /**< Deprecated; Total nb. of XOFF pause frame received. */
uint64_t q_ipackets[RTE_ETHDEV_QUEUE_STAT_CNTRS];
/**< Total number of queue RX packets. */
uint64_t q_opackets[RTE_ETHDEV_QUEUE_STAT_CNTRS];
--
1.9.3
^ permalink raw reply [relevance 9%]
* [dpdk-dev] [PATCH v4 0/8] Expose IXGBE extended stats to DPDK apps
@ 2015-07-05 17:39 3% Maryam Tahhan
2015-07-05 17:39 9% ` [dpdk-dev] [PATCH v4 4/8] ethdev: remove HW specific stats in stats structs Maryam Tahhan
0 siblings, 1 reply; 200+ results
From: Maryam Tahhan @ 2015-07-05 17:39 UTC (permalink / raw)
To: dev
This patch set implements xstats_get() and xstats_reset() in dev_ops for
ixgbe to expose detailed error statistics to DPDK applications. The
dump_cfg application was extended to demonstrate the usage of
retrieving statistics for DPDK interfaces and renamed to proc_info
in order reflect this new functionality. This patch set also removes non
generic statistics from the statistics strings at the ethdev level and
marks the relevant registers as depricated in struct rte_eth_stats.
v2:
- Fixed patch dependencies.
- Broke down patches into smaller logical changes.
v3:
- Removes non-generic stats fields in rte_stats_strings and deprecates
the fields related to them in struct rte_eth_stats.
- Modifies rte_eth_xstats_get() to return generic stats and extended stats.
v4:
- Replace count use in the loop in ixgbe_dev_xstats_get() function definition with i.
- Breakdown "ixgbe: add NIC specific stats removed from ethdev" into two patches, one
that adds the stats and another that extends ierrors to include more error stats.
- Remove second call to ixgbe_dev_xstats_get() from rte_eth_xstats_get().
Maryam Tahhan (8):
ixgbe: move stats register reads to a new function
ixgbe: add functions to get and reset xstats
ethdev: expose extended error stats
ethdev: remove HW specific stats in stats structs
ixgbe: add NIC specific stats removed from ethdev
ixgbe: return more errors in ierrors
app: remove dump_cfg
app: add a new app proc_info
MAINTAINERS | 4 +
app/Makefile | 2 +-
app/dump_cfg/Makefile | 45 ----
app/dump_cfg/main.c | 92 -------
app/proc_info/Makefile | 45 ++++
app/proc_info/main.c | 512 +++++++++++++++++++++++++++++++++++++++
doc/guides/rel_notes/abi.rst | 11 +
drivers/net/ixgbe/ixgbe_ethdev.c | 194 ++++++++++++---
lib/librte_ether/rte_ethdev.c | 34 ++-
lib/librte_ether/rte_ethdev.h | 30 ++-
mk/rte.sdktest.mk | 4 +-
11 files changed, 767 insertions(+), 206 deletions(-)
delete mode 100644 app/dump_cfg/Makefile
delete mode 100644 app/dump_cfg/main.c
create mode 100644 app/proc_info/Makefile
create mode 100644 app/proc_info/main.c
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 8/9] doc: announce ABI change of librte_malloc
2015-07-03 9:55 4% ` [dpdk-dev] [PATCH v7 " Sergio Gonzalez Monroy
2015-07-03 9:55 1% ` [dpdk-dev] [PATCH v7 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
@ 2015-07-03 9:55 14% ` Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-07-03 9:55 UTC (permalink / raw)
To: dev
Announce the creation of dummy malloc library for 2.1 and removal of
such library, now integrated in librte_eal, for 2.2 release.
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
doc/guides/rel_notes/abi.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index 110c486..50fb6a5 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -12,3 +12,4 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* librte_malloc library has been integrated into librte_eal. The 2.1 release creates a dummy/empty malloc library to fulfill binaries with dynamic linking dependencies on librte_malloc.so. Such dummy library will not be created from release 2.2 so binaries will need to be rebuilt.
--
1.9.3
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v7 2/9] eal: memzone allocated by malloc
2015-07-03 9:55 4% ` [dpdk-dev] [PATCH v7 " Sergio Gonzalez Monroy
@ 2015-07-03 9:55 1% ` Sergio Gonzalez Monroy
2015-07-03 9:55 14% ` [dpdk-dev] [PATCH v7 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-07-03 9:55 UTC (permalink / raw)
To: dev
In the current memory hierarchy, memsegs are groups of physically
contiguous hugepages, memzones are slices of memsegs and malloc further
slices memzones into smaller memory chunks.
This patch modifies malloc so it partitions memsegs instead of memzones.
Thus memzones would call malloc internally for memory allocation while
maintaining its ABI.
It would be possible to free memzones and therefore any other structure
based on memzones, ie. mempools
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
lib/librte_eal/common/eal_common_memzone.c | 274 ++++++----------------
lib/librte_eal/common/include/rte_eal_memconfig.h | 2 +-
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/malloc_elem.c | 68 ++++--
lib/librte_eal/common/malloc_elem.h | 14 +-
lib/librte_eal/common/malloc_heap.c | 140 ++++++-----
lib/librte_eal/common/malloc_heap.h | 6 +-
lib/librte_eal/common/rte_malloc.c | 7 +-
8 files changed, 197 insertions(+), 317 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index aee184a..943012b 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -50,15 +50,15 @@
#include <rte_string_fns.h>
#include <rte_common.h>
+#include "malloc_heap.h"
+#include "malloc_elem.h"
#include "eal_private.h"
-/* internal copy of free memory segments */
-static struct rte_memseg *free_memseg = NULL;
-
static inline const struct rte_memzone *
memzone_lookup_thread_unsafe(const char *name)
{
const struct rte_mem_config *mcfg;
+ const struct rte_memzone *mz;
unsigned i = 0;
/* get pointer to global configuration */
@@ -68,8 +68,9 @@ memzone_lookup_thread_unsafe(const char *name)
* the algorithm is not optimal (linear), but there are few
* zones and this function should be called at init only
*/
- for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) {
- if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE))
+ for (i = 0; i < RTE_MAX_MEMZONE; i++) {
+ mz = &mcfg->memzone[i];
+ if (mz->addr != NULL && !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE))
return &mcfg->memzone[i];
}
@@ -88,39 +89,45 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id,
len, socket_id, flags, RTE_CACHE_LINE_SIZE);
}
-/*
- * Helper function for memzone_reserve_aligned_thread_unsafe().
- * Calculate address offset from the start of the segment.
- * Align offset in that way that it satisfy istart alignmnet and
- * buffer of the requested length would not cross specified boundary.
- */
-static inline phys_addr_t
-align_phys_boundary(const struct rte_memseg *ms, size_t len, size_t align,
- size_t bound)
+/* Find the heap with the greatest free block size */
+static void
+find_heap_max_free_elem(int *s, size_t *len, unsigned align)
{
- phys_addr_t addr_offset, bmask, end, start;
- size_t step;
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- step = RTE_MAX(align, bound);
- bmask = ~((phys_addr_t)bound - 1);
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate offset to closest alignment */
- start = RTE_ALIGN_CEIL(ms->phys_addr, align);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size > *len) {
+ *len = stats.greatest_free_size;
+ *s = i;
+ }
+ }
+ *len -= (MALLOC_ELEM_OVERHEAD + align);
+}
- while (addr_offset + len < ms->len) {
+/* Find a heap that can allocate the requested size */
+static void
+find_heap_suitable(int *s, size_t len, unsigned align)
+{
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- /* check, do we meet boundary condition */
- end = start + len - (len != 0);
- if ((start & bmask) == (end & bmask))
- break;
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate next offset */
- start = RTE_ALIGN_CEIL(start + 1, step);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size >= len + MALLOC_ELEM_OVERHEAD + align) {
+ *s = i;
+ break;
+ }
}
-
- return addr_offset;
}
static const struct rte_memzone *
@@ -128,13 +135,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
int socket_id, unsigned flags, unsigned align, unsigned bound)
{
struct rte_mem_config *mcfg;
- unsigned i = 0;
- int memseg_idx = -1;
- uint64_t addr_offset, seg_offset = 0;
size_t requested_len;
- size_t memseg_len = 0;
- phys_addr_t memseg_physaddr;
- void *memseg_addr;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
@@ -166,7 +167,6 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
if (align < RTE_CACHE_LINE_SIZE)
align = RTE_CACHE_LINE_SIZE;
-
/* align length on cache boundary. Check for overflow before doing so */
if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) {
rte_errno = EINVAL; /* requested size too big */
@@ -180,129 +180,50 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len);
/* check that boundary condition is valid */
- if (bound != 0 &&
- (requested_len > bound || !rte_is_power_of_2(bound))) {
+ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) {
rte_errno = EINVAL;
return NULL;
}
- /* find the smallest segment matching requirements */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- /* last segment */
- if (free_memseg[i].addr == NULL)
- break;
+ if (len == 0) {
+ if (bound != 0)
+ requested_len = bound;
+ else
+ requested_len = 0;
+ }
- /* empty segment, skip it */
- if (free_memseg[i].len == 0)
- continue;
-
- /* bad socket ID */
- if (socket_id != SOCKET_ID_ANY &&
- free_memseg[i].socket_id != SOCKET_ID_ANY &&
- socket_id != free_memseg[i].socket_id)
- continue;
-
- /*
- * calculate offset to closest alignment that
- * meets boundary conditions.
- */
- addr_offset = align_phys_boundary(free_memseg + i,
- requested_len, align, bound);
-
- /* check len */
- if ((requested_len + addr_offset) > free_memseg[i].len)
- continue;
-
- /* check flags for hugepage sizes */
- if ((flags & RTE_MEMZONE_2MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_1G)
- continue;
- if ((flags & RTE_MEMZONE_1GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_2M)
- continue;
- if ((flags & RTE_MEMZONE_16MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16G)
- continue;
- if ((flags & RTE_MEMZONE_16GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16M)
- continue;
-
- /* this segment is the best until now */
- if (memseg_idx == -1) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- /* find the biggest contiguous zone */
- else if (len == 0) {
- if (free_memseg[i].len > memseg_len) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- }
- /*
- * find the smallest (we already checked that current
- * zone length is > len
- */
- else if (free_memseg[i].len + align < memseg_len ||
- (free_memseg[i].len <= memseg_len + align &&
- addr_offset < seg_offset)) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
+ if (socket_id == SOCKET_ID_ANY) {
+ if (requested_len == 0)
+ find_heap_max_free_elem(&socket_id, &requested_len, align);
+ else
+ find_heap_suitable(&socket_id, requested_len, align);
+
+ if (socket_id == SOCKET_ID_ANY) {
+ rte_errno = ENOMEM;
+ return NULL;
}
}
- /* no segment found */
- if (memseg_idx == -1) {
- /*
- * If RTE_MEMZONE_SIZE_HINT_ONLY flag is specified,
- * try allocating again without the size parameter otherwise -fail.
- */
- if ((flags & RTE_MEMZONE_SIZE_HINT_ONLY) &&
- ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB)
- || (flags & RTE_MEMZONE_16MB) || (flags & RTE_MEMZONE_16GB)))
- return memzone_reserve_aligned_thread_unsafe(name,
- len, socket_id, 0, align, bound);
-
+ /* allocate memory on heap */
+ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket_id], NULL,
+ requested_len, flags, align, bound);
+ if (mz_addr == NULL) {
rte_errno = ENOMEM;
return NULL;
}
- /* save aligned physical and virtual addresses */
- memseg_physaddr = free_memseg[memseg_idx].phys_addr + seg_offset;
- memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr,
- (uintptr_t) seg_offset);
-
- /* if we are looking for a biggest memzone */
- if (len == 0) {
- if (bound == 0)
- requested_len = memseg_len - seg_offset;
- else
- requested_len = RTE_ALIGN_CEIL(memseg_physaddr + 1,
- bound) - memseg_physaddr;
- }
-
- /* set length to correct value */
- len = (size_t)seg_offset + requested_len;
-
- /* update our internal state */
- free_memseg[memseg_idx].len -= len;
- free_memseg[memseg_idx].phys_addr += len;
- free_memseg[memseg_idx].addr =
- (char *)free_memseg[memseg_idx].addr + len;
+ const struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
/* fill the zone in config */
struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++];
snprintf(mz->name, sizeof(mz->name), "%s", name);
- mz->phys_addr = memseg_physaddr;
- mz->addr = memseg_addr;
- mz->len = requested_len;
- mz->hugepage_sz = free_memseg[memseg_idx].hugepage_sz;
- mz->socket_id = free_memseg[memseg_idx].socket_id;
+ mz->phys_addr = rte_malloc_virt2phy(mz_addr);
+ mz->addr = mz_addr;
+ mz->len = (requested_len == 0 ? elem->size : requested_len);
+ mz->hugepage_sz = elem->ms->hugepage_sz;
+ mz->socket_id = elem->ms->socket_id;
mz->flags = 0;
- mz->memseg_id = memseg_idx;
+ mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg;
return mz;
}
@@ -419,45 +340,6 @@ rte_memzone_dump(FILE *f)
}
/*
- * called by init: modify the free memseg list to have cache-aligned
- * addresses and cache-aligned lengths
- */
-static int
-memseg_sanitize(struct rte_memseg *memseg)
-{
- unsigned phys_align;
- unsigned virt_align;
- unsigned off;
-
- phys_align = memseg->phys_addr & RTE_CACHE_LINE_MASK;
- virt_align = (unsigned long)memseg->addr & RTE_CACHE_LINE_MASK;
-
- /*
- * sanity check: phys_addr and addr must have the same
- * alignment
- */
- if (phys_align != virt_align)
- return -1;
-
- /* memseg is really too small, don't bother with it */
- if (memseg->len < (2 * RTE_CACHE_LINE_SIZE)) {
- memseg->len = 0;
- return 0;
- }
-
- /* align start address */
- off = (RTE_CACHE_LINE_SIZE - phys_align) & RTE_CACHE_LINE_MASK;
- memseg->phys_addr += off;
- memseg->addr = (char *)memseg->addr + off;
- memseg->len -= off;
-
- /* align end address */
- memseg->len &= ~((uint64_t)RTE_CACHE_LINE_MASK);
-
- return 0;
-}
-
-/*
* Init the memzone subsystem
*/
int
@@ -465,14 +347,10 @@ rte_eal_memzone_init(void)
{
struct rte_mem_config *mcfg;
const struct rte_memseg *memseg;
- unsigned i = 0;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
- /* mirror the runtime memsegs from config */
- free_memseg = mcfg->free_memseg;
-
/* secondary processes don't need to initialise anything */
if (rte_eal_process_type() == RTE_PROC_SECONDARY)
return 0;
@@ -485,33 +363,13 @@ rte_eal_memzone_init(void)
rte_rwlock_write_lock(&mcfg->mlock);
- /* fill in uninitialized free_memsegs */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (memseg[i].addr == NULL)
- break;
- if (free_memseg[i].addr != NULL)
- continue;
- memcpy(&free_memseg[i], &memseg[i], sizeof(struct rte_memseg));
- }
-
- /* make all zones cache-aligned */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (free_memseg[i].addr == NULL)
- break;
- if (memseg_sanitize(&free_memseg[i]) < 0) {
- RTE_LOG(ERR, EAL, "%s(): Sanity check failed\n", __func__);
- rte_rwlock_write_unlock(&mcfg->mlock);
- return -1;
- }
- }
-
/* delete all zones */
mcfg->memzone_idx = 0;
memset(mcfg->memzone, 0, sizeof(mcfg->memzone));
rte_rwlock_write_unlock(&mcfg->mlock);
- return 0;
+ return rte_eal_malloc_heap_init();
}
/* Walk all reserved memory zones */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 34f5abc..055212a 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -73,7 +73,7 @@ struct rte_mem_config {
struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */
struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */
- /* Runtime Physmem descriptors. */
+ /* Runtime Physmem descriptors - NOT USED */
struct rte_memseg free_memseg[RTE_MAX_MEMSEG];
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h
index 716216f..b270356 100644
--- a/lib/librte_eal/common/include/rte_malloc_heap.h
+++ b/lib/librte_eal/common/include/rte_malloc_heap.h
@@ -40,7 +40,7 @@
#include <rte_memory.h>
/* Number of free lists per heap, grouped by size. */
-#define RTE_HEAP_NUM_FREELISTS 5
+#define RTE_HEAP_NUM_FREELISTS 13
/**
* Structure to hold malloc heap
@@ -48,7 +48,6 @@
struct malloc_heap {
rte_spinlock_t lock;
LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS];
- unsigned mz_count;
unsigned alloc_count;
size_t total_size;
} __rte_cache_aligned;
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index a5e1248..b54ee33 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -37,7 +37,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include <rte_per_lcore.h>
@@ -56,10 +55,10 @@
*/
void
malloc_elem_init(struct malloc_elem *elem,
- struct malloc_heap *heap, const struct rte_memzone *mz, size_t size)
+ struct malloc_heap *heap, const struct rte_memseg *ms, size_t size)
{
elem->heap = heap;
- elem->mz = mz;
+ elem->ms = ms;
elem->prev = NULL;
memset(&elem->free_list, 0, sizeof(elem->free_list));
elem->state = ELEM_FREE;
@@ -70,12 +69,12 @@ malloc_elem_init(struct malloc_elem *elem,
}
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
{
- malloc_elem_init(elem, prev->heap, prev->mz, 0);
+ malloc_elem_init(elem, prev->heap, prev->ms, 0);
elem->prev = prev;
elem->state = ELEM_BUSY; /* mark busy so its never merged */
}
@@ -86,12 +85,24 @@ malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
* fit, return NULL.
*/
static void *
-elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
+elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- const uintptr_t end_pt = (uintptr_t)elem +
+ const size_t bmask = ~(bound - 1);
+ uintptr_t end_pt = (uintptr_t)elem +
elem->size - MALLOC_ELEM_TRAILER_LEN;
- const uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
- const uintptr_t new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
+ uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ uintptr_t new_elem_start;
+
+ /* check boundary */
+ if ((new_data_start & bmask) != ((end_pt - 1) & bmask)) {
+ end_pt = RTE_ALIGN_FLOOR(end_pt, bound);
+ new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ if (((end_pt - 1) & bmask) != (new_data_start & bmask))
+ return NULL;
+ }
+
+ new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
/* if the new start point is before the exist start, it won't fit */
return (new_elem_start < (uintptr_t)elem) ? NULL : (void *)new_elem_start;
@@ -102,9 +113,10 @@ elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
* alignment request from the current element
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- return elem_start_pt(elem, size, align) != NULL;
+ return elem_start_pt(elem, size, align, bound) != NULL;
}
/*
@@ -115,10 +127,10 @@ static void
split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)
{
struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size);
- const unsigned old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
- const unsigned new_elem_size = elem->size - old_elem_size;
+ const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
+ const size_t new_elem_size = elem->size - old_elem_size;
- malloc_elem_init(split_pt, elem->heap, elem->mz, new_elem_size);
+ malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size);
split_pt->prev = elem;
next_elem->prev = split_pt;
elem->size = old_elem_size;
@@ -168,8 +180,9 @@ malloc_elem_free_list_index(size_t size)
void
malloc_elem_free_list_insert(struct malloc_elem *elem)
{
- size_t idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
+ size_t idx;
+ idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
elem->state = ELEM_FREE;
LIST_INSERT_HEAD(&elem->heap->free_head[idx], elem, free_list);
}
@@ -190,12 +203,26 @@ elem_free_list_remove(struct malloc_elem *elem)
* is not done here, as it's done there previously.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- struct malloc_elem *new_elem = elem_start_pt(elem, size, align);
- const unsigned old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound);
+ const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ const size_t trailer_size = elem->size - old_elem_size - size -
+ MALLOC_ELEM_OVERHEAD;
+
+ elem_free_list_remove(elem);
- if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE){
+ if (trailer_size > MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* split it, too much free space after elem */
+ struct malloc_elem *new_free_elem =
+ RTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD);
+
+ split_elem(elem, new_free_elem);
+ malloc_elem_free_list_insert(new_free_elem);
+ }
+
+ if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
/* don't split it, pad the element instead */
elem->state = ELEM_BUSY;
elem->pad = old_elem_size;
@@ -208,8 +235,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
new_elem->size = elem->size - elem->pad;
set_header(new_elem);
}
- /* remove element from free list */
- elem_free_list_remove(elem);
return new_elem;
}
@@ -219,7 +244,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
* Re-insert original element, in case its new size makes it
* belong on a different list.
*/
- elem_free_list_remove(elem);
split_elem(elem, new_elem);
new_elem->state = ELEM_BUSY;
malloc_elem_free_list_insert(elem);
diff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h
index 9790b1a..e05d2ea 100644
--- a/lib/librte_eal/common/malloc_elem.h
+++ b/lib/librte_eal/common/malloc_elem.h
@@ -47,9 +47,9 @@ enum elem_state {
struct malloc_elem {
struct malloc_heap *heap;
- struct malloc_elem *volatile prev; /* points to prev elem in memzone */
+ struct malloc_elem *volatile prev; /* points to prev elem in memseg */
LIST_ENTRY(malloc_elem) free_list; /* list of free elements in heap */
- const struct rte_memzone *mz;
+ const struct rte_memseg *ms;
volatile enum elem_state state;
uint32_t pad;
size_t size;
@@ -136,11 +136,11 @@ malloc_elem_from_data(const void *data)
void
malloc_elem_init(struct malloc_elem *elem,
struct malloc_heap *heap,
- const struct rte_memzone *mz,
+ const struct rte_memseg *ms,
size_t size);
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem,
@@ -151,14 +151,16 @@ malloc_elem_mkend(struct malloc_elem *elem,
* of the requested size and with the requested alignment
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* reserve a block of data in an existing malloc_elem. If the malloc_elem
* is much larger than the data block requested, we split the element in two.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_alloc(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* free a malloc_elem block by adding it to the free list. If the
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 8861d27..f5fff96 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -39,7 +39,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_launch.h>
@@ -54,123 +53,104 @@
#include "malloc_elem.h"
#include "malloc_heap.h"
-/* since the memzone size starts with a digit, it will appear unquoted in
- * rte_config.h, so quote it so it can be passed to rte_str_to_size */
-#define MALLOC_MEMZONE_SIZE RTE_STR(RTE_MALLOC_MEMZONE_SIZE)
-
-/*
- * returns the configuration setting for the memzone size as a size_t value
- */
-static inline size_t
-get_malloc_memzone_size(void)
+static unsigned
+check_hugepage_sz(unsigned flags, size_t hugepage_sz)
{
- return rte_str_to_size(MALLOC_MEMZONE_SIZE);
+ unsigned ret = 1;
+
+ if ((flags & RTE_MEMZONE_2MB) && hugepage_sz == RTE_PGSIZE_1G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_1GB) && hugepage_sz == RTE_PGSIZE_2M)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16MB) && hugepage_sz == RTE_PGSIZE_16G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16GB) && hugepage_sz == RTE_PGSIZE_16M)
+ ret = 0;
+
+ return ret;
}
/*
- * reserve an extra memory zone and make it available for use by a particular
- * heap. This reserves the zone and sets a dummy malloc_elem header at the end
+ * Expand the heap with a memseg.
+ * This reserves the zone and sets a dummy malloc_elem header at the end
* to prevent overflow. The rest of the zone is added to free list as a single
* large free block
*/
-static int
-malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
+static void
+malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)
{
- const unsigned mz_flags = 0;
- const size_t block_size = get_malloc_memzone_size();
- /* ensure the data we want to allocate will fit in the memzone */
- const size_t min_size = size + align + MALLOC_ELEM_OVERHEAD * 2;
- const struct rte_memzone *mz = NULL;
- struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
- unsigned numa_socket = heap - mcfg->malloc_heaps;
-
- size_t mz_size = min_size;
- if (mz_size < block_size)
- mz_size = block_size;
-
- char mz_name[RTE_MEMZONE_NAMESIZE];
- snprintf(mz_name, sizeof(mz_name), "MALLOC_S%u_HEAP_%u",
- numa_socket, heap->mz_count++);
-
- /* try getting a block. if we fail and we don't need as big a block
- * as given in the config, we can shrink our request and try again
- */
- do {
- mz = rte_memzone_reserve(mz_name, mz_size, numa_socket,
- mz_flags);
- if (mz == NULL)
- mz_size /= 2;
- } while (mz == NULL && mz_size > min_size);
- if (mz == NULL)
- return -1;
-
/* allocate the memory block headers, one at end, one at start */
- struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
- struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
- mz_size - MALLOC_ELEM_OVERHEAD);
+ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr;
+ struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr,
+ ms->len - MALLOC_ELEM_OVERHEAD);
end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);
+ const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- malloc_elem_init(start_elem, heap, mz, elem_size);
+ malloc_elem_init(start_elem, heap, ms, elem_size);
malloc_elem_mkend(end_elem, start_elem);
malloc_elem_free_list_insert(start_elem);
- /* increase heap total size by size of new memzone */
- heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
- return 0;
+ heap->total_size += elem_size;
}
/*
* Iterates through the freelist for a heap to find a free element
* which can store data of the required size and with the requested alignment.
+ * If size is 0, find the biggest available elem.
* Returns null on failure, or pointer to element on success.
*/
static struct malloc_elem *
-find_suitable_element(struct malloc_heap *heap, size_t size, unsigned align)
+find_suitable_element(struct malloc_heap *heap, size_t size,
+ unsigned flags, size_t align, size_t bound)
{
size_t idx;
- struct malloc_elem *elem;
+ struct malloc_elem *elem, *alt_elem = NULL;
for (idx = malloc_elem_free_list_index(size);
- idx < RTE_HEAP_NUM_FREELISTS; idx++)
- {
+ idx < RTE_HEAP_NUM_FREELISTS; idx++) {
for (elem = LIST_FIRST(&heap->free_head[idx]);
- !!elem; elem = LIST_NEXT(elem, free_list))
- {
- if (malloc_elem_can_hold(elem, size, align))
- return elem;
+ !!elem; elem = LIST_NEXT(elem, free_list)) {
+ if (malloc_elem_can_hold(elem, size, align, bound)) {
+ if (check_hugepage_sz(flags, elem->ms->hugepage_sz))
+ return elem;
+ alt_elem = elem;
+ }
}
}
+
+ if ((alt_elem != NULL) && (flags & RTE_MEMZONE_SIZE_HINT_ONLY))
+ return alt_elem;
+
return NULL;
}
/*
- * Main function called by malloc to allocate a block of memory from the
- * heap. It locks the free list, scans it, and adds a new memzone if the
- * scan fails. Once the new memzone is added, it re-scans and should return
+ * Main function to allocate a block of memory from the heap.
+ * It locks the free list, scans it, and adds a new memseg if the
+ * scan fails. Once the new memseg is added, it re-scans and should return
* the new element after releasing the lock.
*/
void *
malloc_heap_alloc(struct malloc_heap *heap,
- const char *type __attribute__((unused)), size_t size, unsigned align)
+ const char *type __attribute__((unused)), size_t size, unsigned flags,
+ size_t align, size_t bound)
{
+ struct malloc_elem *elem;
+
size = RTE_CACHE_LINE_ROUNDUP(size);
align = RTE_CACHE_LINE_ROUNDUP(align);
+
rte_spinlock_lock(&heap->lock);
- struct malloc_elem *elem = find_suitable_element(heap, size, align);
- if (elem == NULL){
- if ((malloc_heap_add_memzone(heap, size, align)) == 0)
- elem = find_suitable_element(heap, size, align);
- }
- if (elem != NULL){
- elem = malloc_elem_alloc(elem, size, align);
+ elem = find_suitable_element(heap, size, flags, align, bound);
+ if (elem != NULL) {
+ elem = malloc_elem_alloc(elem, size, align, bound);
/* increase heap's count of allocated elements */
heap->alloc_count++;
}
rte_spinlock_unlock(&heap->lock);
- return elem == NULL ? NULL : (void *)(&elem[1]);
+ return elem == NULL ? NULL : (void *)(&elem[1]);
}
/*
@@ -206,3 +186,21 @@ malloc_heap_get_stats(const struct malloc_heap *heap,
socket_stats->alloc_count = heap->alloc_count;
return 0;
}
+
+int
+rte_eal_malloc_heap_init(void)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ unsigned ms_cnt;
+ struct rte_memseg *ms;
+
+ if (mcfg == NULL)
+ return -1;
+
+ for (ms = &mcfg->memseg[0], ms_cnt = 0;
+ (ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0);
+ ms_cnt++, ms++)
+ malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms);
+
+ return 0;
+}
diff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h
index a47136d..3ccbef0 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -53,15 +53,15 @@ malloc_get_numa_socket(void)
}
void *
-malloc_heap_alloc(struct malloc_heap *heap, const char *type,
- size_t size, unsigned align);
+malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size,
+ unsigned flags, size_t align, size_t bound);
int
malloc_heap_get_stats(const struct malloc_heap *heap,
struct rte_malloc_socket_stats *socket_stats);
int
-rte_eal_heap_memzone_init(void);
+rte_eal_malloc_heap_init(void);
#ifdef __cplusplus
}
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index c313a57..54c2bd8 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -39,7 +39,6 @@
#include <rte_memcpy.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_branch_prediction.h>
@@ -87,7 +86,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
return NULL;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL || socket_arg != SOCKET_ID_ANY)
return ret;
@@ -98,7 +97,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
continue;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL)
return ret;
}
@@ -256,5 +255,5 @@ rte_malloc_virt2phy(const void *addr)
const struct malloc_elem *elem = malloc_elem_from_data(addr);
if (elem == NULL)
return 0;
- return elem->mz->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->mz->addr);
+ return elem->ms->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->ms->addr);
}
--
1.9.3
^ permalink raw reply [relevance 1%]
* [dpdk-dev] [PATCH v7 0/9] Dynamic memzones
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
` (2 preceding siblings ...)
2015-06-26 16:13 0% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Ananyev, Konstantin
@ 2015-07-03 9:55 4% ` Sergio Gonzalez Monroy
2015-07-03 9:55 1% ` [dpdk-dev] [PATCH v7 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-07-03 9:55 14% ` [dpdk-dev] [PATCH v7 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
3 siblings, 2 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-07-03 9:55 UTC (permalink / raw)
To: dev
Current implemetation allows reserving/creating memzones but not the opposite
(unreserve/free). This affects mempools and other memzone based objects.
>From my point of view, implementing free functionality for memzones would look
like malloc over memsegs.
Thus, this approach moves malloc inside eal (which in turn removes a circular
dependency), where malloc heaps are composed of memsegs.
We keep both malloc and memzone APIs as they are, but memzones allocate its
memory by calling malloc_heap_alloc.
Some extra functionality is required in malloc to allow for boundary constrained
memory requests.
In summary, currently malloc is based on memzones, and with this approach
memzones are based on malloc.
v7:
- Create a separated maintainer section for memory allocation
v6:
- Fix bad patch for rte_memzone_free
v5:
- Fix rte_memzone_free
- Improve rte_memzone_free unit test
v4:
- Rebase and fix couple of merge issues
v3:
- Create dummy librte_malloc
- Add deprecation notice
- Rework some of the code
- Doc update
- checkpatch
v2:
- New rte_memzone_free
- Support memzone len = 0
- Add all available memsegs to malloc heap at init
- Update memzone/malloc unit tests
Sergio Gonzalez Monroy (9):
eal: move librte_malloc to eal/common
eal: memzone allocated by malloc
app/test: update malloc/memzone unit tests
config: remove CONFIG_RTE_MALLOC_MEMZONE_SIZE
eal: remove free_memseg and references to it
eal: new rte_memzone_free
app/test: rte_memzone_free unit test
doc: announce ABI change of librte_malloc
doc: update malloc documentation
MAINTAINERS | 22 +-
app/test/test_malloc.c | 86 ----
app/test/test_memzone.c | 456 ++++------------------
config/common_bsdapp | 8 +-
config/common_linuxapp | 8 +-
doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++++++++-
doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 80952 bytes
doc/guides/prog_guide/index.rst | 1 -
doc/guides/prog_guide/malloc_lib.rst | 233 -----------
doc/guides/prog_guide/overview.rst | 11 +-
doc/guides/rel_notes/abi.rst | 1 +
drivers/net/af_packet/Makefile | 1 -
drivers/net/bonding/Makefile | 1 -
drivers/net/e1000/Makefile | 2 +-
drivers/net/enic/Makefile | 2 +-
drivers/net/fm10k/Makefile | 2 +-
drivers/net/i40e/Makefile | 2 +-
drivers/net/ixgbe/Makefile | 2 +-
drivers/net/mlx4/Makefile | 1 -
drivers/net/null/Makefile | 1 -
drivers/net/pcap/Makefile | 1 -
drivers/net/virtio/Makefile | 2 +-
drivers/net/vmxnet3/Makefile | 2 +-
drivers/net/xenvirt/Makefile | 2 +-
lib/Makefile | 2 +-
lib/librte_acl/Makefile | 2 +-
lib/librte_eal/bsdapp/eal/Makefile | 4 +-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 19 +
lib/librte_eal/common/Makefile | 1 +
lib/librte_eal/common/eal_common_memzone.c | 339 ++++++----------
lib/librte_eal/common/include/rte_eal_memconfig.h | 5 +-
lib/librte_eal/common/include/rte_malloc.h | 342 ++++++++++++++++
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/include/rte_memzone.h | 11 +
lib/librte_eal/common/malloc_elem.c | 344 ++++++++++++++++
lib/librte_eal/common/malloc_elem.h | 192 +++++++++
lib/librte_eal/common/malloc_heap.c | 206 ++++++++++
lib/librte_eal/common/malloc_heap.h | 70 ++++
lib/librte_eal/common/rte_malloc.c | 259 ++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 4 +-
lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 +-
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 19 +
lib/librte_hash/Makefile | 2 +-
lib/librte_lpm/Makefile | 2 +-
lib/librte_malloc/Makefile | 6 +-
lib/librte_malloc/malloc_elem.c | 320 ---------------
lib/librte_malloc/malloc_elem.h | 190 ---------
lib/librte_malloc/malloc_heap.c | 208 ----------
lib/librte_malloc/malloc_heap.h | 70 ----
lib/librte_malloc/rte_malloc.c | 228 +----------
lib/librte_malloc/rte_malloc.h | 342 ----------------
lib/librte_malloc/rte_malloc_version.map | 16 -
lib/librte_mempool/Makefile | 2 -
lib/librte_port/Makefile | 1 -
lib/librte_ring/Makefile | 3 +-
lib/librte_table/Makefile | 1 -
56 files changed, 1938 insertions(+), 2359 deletions(-)
delete mode 100644 doc/guides/prog_guide/malloc_lib.rst
create mode 100644 lib/librte_eal/common/include/rte_malloc.h
create mode 100644 lib/librte_eal/common/malloc_elem.c
create mode 100644 lib/librte_eal/common/malloc_elem.h
create mode 100644 lib/librte_eal/common/malloc_heap.c
create mode 100644 lib/librte_eal/common/malloc_heap.h
create mode 100644 lib/librte_eal/common/rte_malloc.c
delete mode 100644 lib/librte_malloc/malloc_elem.c
delete mode 100644 lib/librte_malloc/malloc_elem.h
delete mode 100644 lib/librte_malloc/malloc_heap.c
delete mode 100644 lib/librte_malloc/malloc_heap.h
delete mode 100644 lib/librte_malloc/rte_malloc.h
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v2] doc: announce ABI changes planned for unified packet type
@ 2015-07-03 8:49 21% ` Helin Zhang
0 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:49 UTC (permalink / raw)
To: dev
The significant ABI changes are planned for unified packet type
which will be supported from release 2.2. Here announces that ABI
changes in detail.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
doc/guides/rel_notes/abi.rst | 1 +
1 file changed, 1 insertion(+)
v2 changes:
* Added 'struct rte_kni_mbuf' to the ABI change announcement.
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index 110c486..4328367 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -12,3 +12,4 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* Significant ABI changes are planned for struct rte_mbuf, struct rte_kni_mbuf, and several PKT_RX_ flags will be removed, to support unified packet type from release 2.2. The upcoming release 2.1 will not have those changes. There is no backward compatibility planned from release 2.2. All binaries will need to be rebuilt from release 2.2.
--
1.9.3
^ permalink raw reply [relevance 21%]
* [dpdk-dev] [PATCH v9 19/19] mbuf: remove old packet type bit masks
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (17 preceding siblings ...)
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 18/19] examples/tep_termination: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
As unified packet types are used instead, those old bit masks and
the relevant macros for packet type indication need to be removed.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_mbuf/rte_mbuf.c | 4 ++++
lib/librte_mbuf/rte_mbuf.h | 4 ++++
2 files changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
* Redefined the bit masks for packet RX offload flags.
v5 changes:
* Rolled back the bit masks of RX flags, for ABI compatibility.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index f506517..4320dd4 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -251,14 +251,18 @@ const char *rte_get_rx_ol_flag_name(uint64_t mask)
/* case PKT_RX_HBUF_OVERFLOW: return "PKT_RX_HBUF_OVERFLOW"; */
/* case PKT_RX_RECIP_ERR: return "PKT_RX_RECIP_ERR"; */
/* case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; */
+#ifndef RTE_NEXT_ABI
case PKT_RX_IPV4_HDR: return "PKT_RX_IPV4_HDR";
case PKT_RX_IPV4_HDR_EXT: return "PKT_RX_IPV4_HDR_EXT";
case PKT_RX_IPV6_HDR: return "PKT_RX_IPV6_HDR";
case PKT_RX_IPV6_HDR_EXT: return "PKT_RX_IPV6_HDR_EXT";
+#endif /* RTE_NEXT_ABI */
case PKT_RX_IEEE1588_PTP: return "PKT_RX_IEEE1588_PTP";
case PKT_RX_IEEE1588_TMST: return "PKT_RX_IEEE1588_TMST";
+#ifndef RTE_NEXT_ABI
case PKT_RX_TUNNEL_IPV4_HDR: return "PKT_RX_TUNNEL_IPV4_HDR";
case PKT_RX_TUNNEL_IPV6_HDR: return "PKT_RX_TUNNEL_IPV6_HDR";
+#endif /* RTE_NEXT_ABI */
default: return NULL;
}
}
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 3a17d95..b90c73f 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -92,14 +92,18 @@ extern "C" {
#define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer overflow. */
#define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing error. */
#define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */
+#ifndef RTE_NEXT_ABI
#define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 header. */
#define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with extended IPv4 header. */
#define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 header. */
#define PKT_RX_IPV6_HDR_EXT (1ULL << 8) /**< RX packet with extended IPv6 header. */
+#endif /* RTE_NEXT_ABI */
#define PKT_RX_IEEE1588_PTP (1ULL << 9) /**< RX IEEE1588 L2 Ethernet PT Packet. */
#define PKT_RX_IEEE1588_TMST (1ULL << 10) /**< RX IEEE1588 L2/L4 timestamped packet.*/
+#ifndef RTE_NEXT_ABI
#define PKT_RX_TUNNEL_IPV4_HDR (1ULL << 11) /**< RX tunnel packet with IPv4 header.*/
#define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet with IPv6 header. */
+#endif /* RTE_NEXT_ABI */
#define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR match. */
#define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported if FDIR match. */
#define PKT_RX_QINQ_PKT (1ULL << 15) /**< RX packet with double VLAN stripped. */
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 18/19] examples/tep_termination: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (16 preceding siblings ...)
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 17/19] examples/l3fwd: " Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 19/19] mbuf: remove old packet type bit masks Helin Zhang
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be enabled
by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/tep_termination/vxlan.c | 4 ++++
1 file changed, 4 insertions(+)
v9 changes:
* Used unified packet type to check if it is a VXLAN packet, included in
RTE_NEXT_ABI which is disabled by default.
diff --git a/examples/tep_termination/vxlan.c b/examples/tep_termination/vxlan.c
index b2a2f53..ae4bc9e 100644
--- a/examples/tep_termination/vxlan.c
+++ b/examples/tep_termination/vxlan.c
@@ -180,8 +180,12 @@ decapsulation(struct rte_mbuf *pkt)
* (rfc7348) or that the rx offload flag is set (i40e only
* currently)*/
if (udp_hdr->dst_port != rte_cpu_to_be_16(DEFAULT_VXLAN_PORT) &&
+#ifdef RTE_NEXT_ABI
+ ((pkt->packet_type & RTE_PTYPE_TUNNEL_MASK) == 0)
+#else
(pkt->ol_flags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR)) == 0)
+#endif
return -1;
outer_header_len = info.outer_l2_len + info.outer_l3_len
+ sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 17/19] examples/l3fwd: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (15 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 16/19] examples/l3fwd-power: " Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 18/19] examples/tep_termination: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 19/19] mbuf: remove old packet type bit masks Helin Zhang
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd/main.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 120 insertions(+), 3 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v3 changes:
* Minor bug fixes and enhancements.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 5c22ed1..b1bcb35 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -939,7 +939,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
/* Handle IPv4 headers.*/
ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
sizeof(struct ether_hdr));
@@ -970,8 +974,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
} else {
+#endif
/* Handle IPv6 headers.*/
struct ipv6_hdr *ipv6_hdr;
@@ -990,8 +997,13 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
+#ifdef RTE_NEXT_ABI
+ } else
+ /* Free the mbuf that contains non-IPV4/IPV6 packet */
+ rte_pktmbuf_free(m);
+#else
}
-
+#endif
}
#ifdef DO_RFC_1812_CHECKS
@@ -1015,12 +1027,19 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
* to BAD_PORT value.
*/
static inline __attribute__((always_inline)) void
+#ifdef RTE_NEXT_ABI
+rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype)
+#else
rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t flags)
+#endif
{
uint8_t ihl;
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(ptype)) {
+#else
if ((flags & PKT_RX_IPV4_HDR) != 0) {
-
+#endif
ihl = ipv4_hdr->version_ihl - IPV4_MIN_VER_IHL;
ipv4_hdr->time_to_live--;
@@ -1050,11 +1069,19 @@ get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
struct ipv6_hdr *ipv6_hdr;
struct ether_hdr *eth_hdr;
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
if (pkt->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
if (rte_lpm_lookup(qconf->ipv4_lookup_struct, dst_ipv4,
&next_hop) != 0)
next_hop = portid;
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (pkt->ol_flags & PKT_RX_IPV6_HDR) {
+#endif
eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1);
if (rte_lpm6_lookup(qconf->ipv6_lookup_struct,
@@ -1088,12 +1115,52 @@ process_packet(struct lcore_conf *qconf, struct rte_mbuf *pkt,
ve = val_eth[dp];
dst_port[0] = dp;
+#ifdef RTE_NEXT_ABI
+ rfc1812_process(ipv4_hdr, dst_port, pkt->packet_type);
+#else
rfc1812_process(ipv4_hdr, dst_port, pkt->ol_flags);
+#endif
te = _mm_blend_epi16(te, ve, MASK_ETH);
_mm_store_si128((__m128i *)eth_hdr, te);
}
+#ifdef RTE_NEXT_ABI
+/*
+ * Read packet_type and destination IPV4 addresses from 4 mbufs.
+ */
+static inline void
+processx4_step1(struct rte_mbuf *pkt[FWDSTEP],
+ __m128i *dip,
+ uint32_t *ipv4_flag)
+{
+ struct ipv4_hdr *ipv4_hdr;
+ struct ether_hdr *eth_hdr;
+ uint32_t x0, x1, x2, x3;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[0], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x0 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] = pkt[0]->packet_type & RTE_PTYPE_L3_IPV4;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[1], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x1 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[1]->packet_type;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[2], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x2 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[2]->packet_type;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[3], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x3 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[3]->packet_type;
+
+ dip[0] = _mm_set_epi32(x3, x2, x1, x0);
+}
+#else /* RTE_NEXT_ABI */
/*
* Read ol_flags and destination IPV4 addresses from 4 mbufs.
*/
@@ -1126,14 +1193,24 @@ processx4_step1(struct rte_mbuf *pkt[FWDSTEP], __m128i *dip, uint32_t *flag)
dip[0] = _mm_set_epi32(x3, x2, x1, x0);
}
+#endif /* RTE_NEXT_ABI */
/*
* Lookup into LPM for destination port.
* If lookup fails, use incoming port (portid) as destination port.
*/
static inline void
+#ifdef RTE_NEXT_ABI
+processx4_step2(const struct lcore_conf *qconf,
+ __m128i dip,
+ uint32_t ipv4_flag,
+ uint8_t portid,
+ struct rte_mbuf *pkt[FWDSTEP],
+ uint16_t dprt[FWDSTEP])
+#else
processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag,
uint8_t portid, struct rte_mbuf *pkt[FWDSTEP], uint16_t dprt[FWDSTEP])
+#endif /* RTE_NEXT_ABI */
{
rte_xmm_t dst;
const __m128i bswap_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11,
@@ -1143,7 +1220,11 @@ processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag,
dip = _mm_shuffle_epi8(dip, bswap_mask);
/* if all 4 packets are IPV4. */
+#ifdef RTE_NEXT_ABI
+ if (likely(ipv4_flag)) {
+#else
if (likely(flag != 0)) {
+#endif
rte_lpm_lookupx4(qconf->ipv4_lookup_struct, dip, dprt, portid);
} else {
dst.x = dip;
@@ -1193,6 +1274,16 @@ processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
_mm_store_si128(p[2], te[2]);
_mm_store_si128(p[3], te[3]);
+#ifdef RTE_NEXT_ABI
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1),
+ &dst_port[0], pkt[0]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1),
+ &dst_port[1], pkt[1]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[2] + 1),
+ &dst_port[2], pkt[2]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1),
+ &dst_port[3], pkt[3]->packet_type);
+#else /* RTE_NEXT_ABI */
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1),
&dst_port[0], pkt[0]->ol_flags);
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1),
@@ -1201,6 +1292,7 @@ processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
&dst_port[2], pkt[2]->ol_flags);
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1),
&dst_port[3], pkt[3]->ol_flags);
+#endif /* RTE_NEXT_ABI */
}
/*
@@ -1387,7 +1479,11 @@ main_loop(__attribute__((unused)) void *dummy)
uint16_t *lp;
uint16_t dst_port[MAX_PKT_BURST];
__m128i dip[MAX_PKT_BURST / FWDSTEP];
+#ifdef RTE_NEXT_ABI
+ uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP];
+#else
uint32_t flag[MAX_PKT_BURST / FWDSTEP];
+#endif
uint16_t pnum[MAX_PKT_BURST + 1];
#endif
@@ -1457,6 +1553,18 @@ main_loop(__attribute__((unused)) void *dummy)
*/
int32_t n = RTE_ALIGN_FLOOR(nb_rx, 4);
for (j = 0; j < n ; j+=4) {
+#ifdef RTE_NEXT_ABI
+ uint32_t pkt_type =
+ pkts_burst[j]->packet_type &
+ pkts_burst[j+1]->packet_type &
+ pkts_burst[j+2]->packet_type &
+ pkts_burst[j+3]->packet_type;
+ if (pkt_type & RTE_PTYPE_L3_IPV4) {
+ simple_ipv4_fwd_4pkts(
+ &pkts_burst[j], portid, qconf);
+ } else if (pkt_type &
+ RTE_PTYPE_L3_IPV6) {
+#else /* RTE_NEXT_ABI */
uint32_t ol_flag = pkts_burst[j]->ol_flags
& pkts_burst[j+1]->ol_flags
& pkts_burst[j+2]->ol_flags
@@ -1465,6 +1573,7 @@ main_loop(__attribute__((unused)) void *dummy)
simple_ipv4_fwd_4pkts(&pkts_burst[j],
portid, qconf);
} else if (ol_flag & PKT_RX_IPV6_HDR) {
+#endif /* RTE_NEXT_ABI */
simple_ipv6_fwd_4pkts(&pkts_burst[j],
portid, qconf);
} else {
@@ -1489,13 +1598,21 @@ main_loop(__attribute__((unused)) void *dummy)
for (j = 0; j != k; j += FWDSTEP) {
processx4_step1(&pkts_burst[j],
&dip[j / FWDSTEP],
+#ifdef RTE_NEXT_ABI
+ &ipv4_flag[j / FWDSTEP]);
+#else
&flag[j / FWDSTEP]);
+#endif
}
k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP);
for (j = 0; j != k; j += FWDSTEP) {
processx4_step2(qconf, dip[j / FWDSTEP],
+#ifdef RTE_NEXT_ABI
+ ipv4_flag[j / FWDSTEP], portid,
+#else
flag[j / FWDSTEP], portid,
+#endif
&pkts_burst[j], &dst_port[j]);
}
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 16/19] examples/l3fwd-power: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (14 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 15/19] examples/l3fwd-acl: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 17/19] examples/l3fwd: " Helin Zhang
` (2 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd-power/main.c | 8 ++++++++
1 file changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index d4eba1a..dbbebdd 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -635,7 +635,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
/* Handle IPv4 headers.*/
ipv4_hdr =
rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
@@ -670,8 +674,12 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
}
else {
+#endif
/* Handle IPv6 headers.*/
#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
struct ipv6_hdr *ipv6_hdr;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 15/19] examples/l3fwd-acl: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (13 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 14/19] examples/ip_reassembly: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 16/19] examples/l3fwd-power: " Helin Zhang
` (3 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd-acl/main.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c
index 29cb25e..b2bdf2f 100644
--- a/examples/l3fwd-acl/main.c
+++ b/examples/l3fwd-acl/main.c
@@ -645,10 +645,13 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
struct ipv4_hdr *ipv4_hdr;
struct rte_mbuf *pkt = pkts_in[index];
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR);
if (type == PKT_RX_IPV4_HDR) {
-
+#endif
ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct ipv4_hdr *,
sizeof(struct ether_hdr));
@@ -667,9 +670,11 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
/* Not a valid IPv4 packet */
rte_pktmbuf_free(pkt);
}
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (type == PKT_RX_IPV6_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
acl->m_ipv6[(acl->num_ipv6)++] = pkt;
@@ -687,17 +692,22 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
{
struct rte_mbuf *pkt = pkts_in[index];
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR);
if (type == PKT_RX_IPV4_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
acl->m_ipv4[(acl->num_ipv4)++] = pkt;
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (type == PKT_RX_IPV6_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
acl->m_ipv6[(acl->num_ipv6)++] = pkt;
@@ -745,10 +755,17 @@ send_one_packet(struct rte_mbuf *m, uint32_t res)
/* in the ACL list, drop it */
#ifdef L3FWDACL_DEBUG
if ((res & ACL_DENY_SIGNATURE) != 0) {
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type))
+ dump_acl4_rule(m, res);
+ else if (RTE_ETH_IS_IPV6_HDR(m->packet_type))
+ dump_acl6_rule(m, res);
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR)
dump_acl4_rule(m, res);
else
dump_acl6_rule(m, res);
+#endif /* RTE_NEXT_ABI */
}
#endif
rte_pktmbuf_free(m);
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 12/19] app/test: Remove useless code
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (10 preceding siblings ...)
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 11/19] app/testpmd: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 13/19] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
` (6 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
Severl useless code lines are added accidently, which blocks packet
type unification. They should be deleted at all.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
app/test/packet_burst_generator.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
v4 changes:
* Removed several useless code lines which block packet type unification.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test/packet_burst_generator.c b/app/test/packet_burst_generator.c
index 28d9e25..d9d808b 100644
--- a/app/test/packet_burst_generator.c
+++ b/app/test/packet_burst_generator.c
@@ -273,19 +273,21 @@ nomore_mbuf:
if (ipv4) {
pkt->vlan_tci = ETHER_TYPE_IPv4;
pkt->l3_len = sizeof(struct ipv4_hdr);
-
+#ifndef RTE_NEXT_ABI
if (vlan_enabled)
pkt->ol_flags = PKT_RX_IPV4_HDR | PKT_RX_VLAN_PKT;
else
pkt->ol_flags = PKT_RX_IPV4_HDR;
+#endif
} else {
pkt->vlan_tci = ETHER_TYPE_IPv6;
pkt->l3_len = sizeof(struct ipv6_hdr);
-
+#ifndef RTE_NEXT_ABI
if (vlan_enabled)
pkt->ol_flags = PKT_RX_IPV6_HDR | PKT_RX_VLAN_PKT;
else
pkt->ol_flags = PKT_RX_IPV6_HDR;
+#endif
}
pkts_burst[nb_pkt] = pkt;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 14/19] examples/ip_reassembly: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (12 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 13/19] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 15/19] examples/l3fwd-acl: " Helin Zhang
` (4 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/ip_reassembly/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c
index 9ecb6f9..f1c47ad 100644
--- a/examples/ip_reassembly/main.c
+++ b/examples/ip_reassembly/main.c
@@ -356,7 +356,11 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue,
dst_port = portid;
/* if packet is IPv4 */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & (PKT_RX_IPV4_HDR)) {
+#endif
struct ipv4_hdr *ip_hdr;
uint32_t ip_dst;
@@ -396,9 +400,14 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue,
}
eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4);
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ /* if packet is IPv6 */
+#else
}
/* if packet is IPv6 */
else if (m->ol_flags & (PKT_RX_IPV6_HDR | PKT_RX_IPV6_HDR_EXT)) {
+#endif
struct ipv6_extension_fragment *frag_hdr;
struct ipv6_hdr *ip_hdr;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 13/19] examples/ip_fragmentation: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (11 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 12/19] app/test: Remove useless code Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 14/19] examples/ip_reassembly: " Helin Zhang
` (5 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/ip_fragmentation/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 0922ba6..b71d05f 100644
--- a/examples/ip_fragmentation/main.c
+++ b/examples/ip_fragmentation/main.c
@@ -283,7 +283,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
len = qconf->tx_mbufs[port_out].len;
/* if this is an IPv4 packet */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
struct ipv4_hdr *ip_hdr;
uint32_t ip_dst;
/* Read the lookup key (i.e. ip_dst) from the input packet */
@@ -317,9 +321,14 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
if (unlikely (len2 < 0))
return;
}
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ /* if this is an IPv6 packet */
+#else
}
/* if this is an IPv6 packet */
else if (m->ol_flags & PKT_RX_IPV6_HDR) {
+#endif
struct ipv6_hdr *ip_hdr;
ipv6 = 1;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 11/19] app/testpmd: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (9 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 10/19] app/test-pipeline: " Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 12/19] app/test: Remove useless code Helin Zhang
` (7 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Jijiang Liu <jijiang.liu@intel.com>
---
app/test-pmd/csumonly.c | 14 ++++
app/test-pmd/rxonly.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 197 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v4 changes:
* Added printing logs of packet types of each received packet in rxonly mode.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
v9 changes:
* Renamed MAC to ETHER in packet type names.
diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
index 4287940..1bf3485 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -202,8 +202,14 @@ parse_ethernet(struct ether_hdr *eth_hdr, struct testpmd_offload_info *info)
/* Parse a vxlan header */
static void
+#ifdef RTE_NEXT_ABI
+parse_vxlan(struct udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info,
+ uint32_t pkt_type)
+#else
parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info,
uint64_t mbuf_olflags)
+#endif
{
struct ether_hdr *eth_hdr;
@@ -211,8 +217,12 @@ parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info,
* (rfc7348) or that the rx offload flag is set (i40e only
* currently) */
if (udp_hdr->dst_port != _htons(4789) &&
+#ifdef RTE_NEXT_ABI
+ RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0)
+#else
(mbuf_olflags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR)) == 0)
+#endif
return;
info->is_tunnel = 1;
@@ -549,7 +559,11 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)
struct udp_hdr *udp_hdr;
udp_hdr = (struct udp_hdr *)((char *)l3_hdr +
info.l3_len);
+#ifdef RTE_NEXT_ABI
+ parse_vxlan(udp_hdr, &info, m->packet_type);
+#else
parse_vxlan(udp_hdr, &info, m->ol_flags);
+#endif
} else if (info.l4_proto == IPPROTO_GRE) {
struct simple_gre_hdr *gre_hdr;
gre_hdr = (struct simple_gre_hdr *)
diff --git a/app/test-pmd/rxonly.c b/app/test-pmd/rxonly.c
index 4a9f86e..632056d 100644
--- a/app/test-pmd/rxonly.c
+++ b/app/test-pmd/rxonly.c
@@ -91,7 +91,11 @@ pkt_burst_receive(struct fwd_stream *fs)
uint64_t ol_flags;
uint16_t nb_rx;
uint16_t i, packet_type;
+#ifdef RTE_NEXT_ABI
+ uint16_t is_encapsulation;
+#else
uint64_t is_encapsulation;
+#endif
#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
uint64_t start_tsc;
@@ -135,8 +139,12 @@ pkt_burst_receive(struct fwd_stream *fs)
ol_flags = mb->ol_flags;
packet_type = mb->packet_type;
+#ifdef RTE_NEXT_ABI
+ is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
+#else
is_encapsulation = ol_flags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR);
+#endif
print_ether_addr(" src=", ð_hdr->s_addr);
print_ether_addr(" - dst=", ð_hdr->d_addr);
@@ -163,6 +171,177 @@ pkt_burst_receive(struct fwd_stream *fs)
if (ol_flags & PKT_RX_QINQ_PKT)
printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
mb->vlan_tci, mb->vlan_tci_outer);
+#ifdef RTE_NEXT_ABI
+ if (mb->packet_type) {
+ uint32_t ptype;
+
+ /* (outer) L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L2_ETHER:
+ printf(" - (outer) L2 type: ETHER");
+ break;
+ case RTE_PTYPE_L2_ETHER_TIMESYNC:
+ printf(" - (outer) L2 type: ETHER_Timesync");
+ break;
+ case RTE_PTYPE_L2_ETHER_ARP:
+ printf(" - (outer) L2 type: ETHER_ARP");
+ break;
+ case RTE_PTYPE_L2_ETHER_LLDP:
+ printf(" - (outer) L2 type: ETHER_LLDP");
+ break;
+ default:
+ printf(" - (outer) L2 type: Unknown");
+ break;
+ }
+
+ /* (outer) L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L3_IPV4:
+ printf(" - (outer) L3 type: IPV4");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT:
+ printf(" - (outer) L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6:
+ printf(" - (outer) L3 type: IPV6");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT:
+ printf(" - (outer) L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV6_EXT_UNKNOWN");
+ break;
+ default:
+ printf(" - (outer) L3 type: Unknown");
+ break;
+ }
+
+ /* (outer) L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L4_TCP:
+ printf(" - (outer) L4 type: TCP");
+ break;
+ case RTE_PTYPE_L4_UDP:
+ printf(" - (outer) L4 type: UDP");
+ break;
+ case RTE_PTYPE_L4_FRAG:
+ printf(" - (outer) L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_L4_SCTP:
+ printf(" - (outer) L4 type: SCTP");
+ break;
+ case RTE_PTYPE_L4_ICMP:
+ printf(" - (outer) L4 type: ICMP");
+ break;
+ case RTE_PTYPE_L4_NONFRAG:
+ printf(" - (outer) L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - (outer) L4 type: Unknown");
+ break;
+ }
+
+ /* packet tunnel type */
+ ptype = mb->packet_type & RTE_PTYPE_TUNNEL_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_TUNNEL_IP:
+ printf(" - Tunnel type: IP");
+ break;
+ case RTE_PTYPE_TUNNEL_GRE:
+ printf(" - Tunnel type: GRE");
+ break;
+ case RTE_PTYPE_TUNNEL_VXLAN:
+ printf(" - Tunnel type: VXLAN");
+ break;
+ case RTE_PTYPE_TUNNEL_NVGRE:
+ printf(" - Tunnel type: NVGRE");
+ break;
+ case RTE_PTYPE_TUNNEL_GENEVE:
+ printf(" - Tunnel type: GENEVE");
+ break;
+ case RTE_PTYPE_TUNNEL_GRENAT:
+ printf(" - Tunnel type: GRENAT");
+ break;
+ default:
+ printf(" - Tunnel type: Unknown");
+ break;
+ }
+
+ /* inner L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L2_ETHER:
+ printf(" - Inner L2 type: ETHER");
+ break;
+ case RTE_PTYPE_INNER_L2_ETHER_VLAN:
+ printf(" - Inner L2 type: ETHER_VLAN");
+ break;
+ default:
+ printf(" - Inner L2 type: Unknown");
+ break;
+ }
+
+ /* inner L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_INNER_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L3_IPV4:
+ printf(" - Inner L3 type: IPV4");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT:
+ printf(" - Inner L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6:
+ printf(" - Inner L3 type: IPV6");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN:
+ printf(" - Inner L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT:
+ printf(" - Inner L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN:
+ printf(" - Inner L3 type: IPV6_EXT_UNKOWN");
+ break;
+ default:
+ printf(" - Inner L3 type: Unknown");
+ break;
+ }
+
+ /* inner L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L4_TCP:
+ printf(" - Inner L4 type: TCP");
+ break;
+ case RTE_PTYPE_INNER_L4_UDP:
+ printf(" - Inner L4 type: UDP");
+ break;
+ case RTE_PTYPE_INNER_L4_FRAG:
+ printf(" - Inner L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_INNER_L4_SCTP:
+ printf(" - Inner L4 type: SCTP");
+ break;
+ case RTE_PTYPE_INNER_L4_ICMP:
+ printf(" - Inner L4 type: ICMP");
+ break;
+ case RTE_PTYPE_INNER_L4_NONFRAG:
+ printf(" - Inner L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - Inner L4 type: Unknown");
+ break;
+ }
+ printf("\n");
+ } else
+ printf("Unknown packet type\n");
+#endif /* RTE_NEXT_ABI */
if (is_encapsulation) {
struct ipv4_hdr *ipv4_hdr;
struct ipv6_hdr *ipv6_hdr;
@@ -176,7 +355,11 @@ pkt_burst_receive(struct fwd_stream *fs)
l2_len = sizeof(struct ether_hdr);
/* Do not support ipv4 option field */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(packet_type)) {
+#else
if (ol_flags & PKT_RX_TUNNEL_IPV4_HDR) {
+#endif
l3_len = sizeof(struct ipv4_hdr);
ipv4_hdr = rte_pktmbuf_mtod_offset(mb,
struct ipv4_hdr *,
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 10/19] app/test-pipeline: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (8 preceding siblings ...)
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 09/19] cxgbe: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 11/19] app/testpmd: " Helin Zhang
` (8 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
app/test-pipeline/pipeline_hash.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test-pipeline/pipeline_hash.c b/app/test-pipeline/pipeline_hash.c
index 4598ad4..aa3f9e5 100644
--- a/app/test-pipeline/pipeline_hash.c
+++ b/app/test-pipeline/pipeline_hash.c
@@ -459,20 +459,33 @@ app_main_loop_rx_metadata(void) {
signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0);
key = RTE_MBUF_METADATA_UINT8_PTR(m, 32);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
ip_hdr = (struct ipv4_hdr *)
&m_data[sizeof(struct ether_hdr)];
ip_dst = ip_hdr->dst_addr;
k32 = (uint32_t *) key;
k32[0] = ip_dst & 0xFFFFFF00;
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
} else {
+#endif
ipv6_hdr = (struct ipv6_hdr *)
&m_data[sizeof(struct ether_hdr)];
ipv6_dst = ipv6_hdr->dst_addr;
memcpy(key, ipv6_dst, 16);
+#ifdef RTE_NEXT_ABI
+ } else
+ continue;
+#else
}
+#endif
*signature = test_hash(key, 0, 0);
}
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 03/19] e1000: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 01/19] mbuf: redefine packet_type in rte_mbuf Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 02/19] mbuf: add definitions of unified packet types Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 04/19] ixgbe: " Helin Zhang
` (15 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/e1000/igb_rxtx.c | 104 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
v9 changes:
* Renamed MAC to ETHER in packet type names.
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index 43d6703..165144c 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -590,6 +590,101 @@ eth_igb_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
* RX functions
*
**********************************************************************/
+#ifdef RTE_NEXT_ABI
+#define IGB_PACKET_TYPE_IPV4 0X01
+#define IGB_PACKET_TYPE_IPV4_TCP 0X11
+#define IGB_PACKET_TYPE_IPV4_UDP 0X21
+#define IGB_PACKET_TYPE_IPV4_SCTP 0X41
+#define IGB_PACKET_TYPE_IPV4_EXT 0X03
+#define IGB_PACKET_TYPE_IPV4_EXT_SCTP 0X43
+#define IGB_PACKET_TYPE_IPV6 0X04
+#define IGB_PACKET_TYPE_IPV6_TCP 0X14
+#define IGB_PACKET_TYPE_IPV6_UDP 0X24
+#define IGB_PACKET_TYPE_IPV6_EXT 0X0C
+#define IGB_PACKET_TYPE_IPV6_EXT_TCP 0X1C
+#define IGB_PACKET_TYPE_IPV6_EXT_UDP 0X2C
+#define IGB_PACKET_TYPE_IPV4_IPV6 0X05
+#define IGB_PACKET_TYPE_IPV4_IPV6_TCP 0X15
+#define IGB_PACKET_TYPE_IPV4_IPV6_UDP 0X25
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT 0X0D
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D
+#define IGB_PACKET_TYPE_MAX 0X80
+#define IGB_PACKET_TYPE_MASK 0X7F
+#define IGB_PACKET_TYPE_SHIFT 0X04
+static inline uint32_t
+igb_rxd_pkt_info_to_pkt_type(uint16_t pkt_info)
+{
+ static const uint32_t
+ ptype_table[IGB_PACKET_TYPE_MAX] __rte_cache_aligned = {
+ [IGB_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4,
+ [IGB_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [IGB_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6,
+ [IGB_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IGB_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ [IGB_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP,
+ [IGB_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP,
+ [IGB_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP,
+ [IGB_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP,
+ };
+ if (unlikely(pkt_info & E1000_RXDADV_PKTTYPE_ETQF))
+ return RTE_PTYPE_UNKNOWN;
+
+ pkt_info = (pkt_info >> IGB_PACKET_TYPE_SHIFT) & IGB_PACKET_TYPE_MASK;
+
+ return ptype_table[pkt_info];
+}
+
+static inline uint64_t
+rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
+{
+ uint64_t pkt_flags = ((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH;
+
+#if defined(RTE_LIBRTE_IEEE1588)
+ static uint32_t ip_pkt_etqf_map[8] = {
+ 0, 0, 0, PKT_RX_IEEE1588_PTP,
+ 0, 0, 0, 0,
+ };
+
+ pkt_flags |= ip_pkt_etqf_map[(hl_tp_rs >> 4) & 0x07];
+#endif
+
+ return pkt_flags;
+}
+#else /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
{
@@ -617,6 +712,7 @@ rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
#endif
return pkt_flags | (((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH);
}
+#endif /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_status_to_pkt_flags(uint32_t rx_status)
@@ -790,6 +886,10 @@ eth_igb_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
rxm->ol_flags = pkt_flags;
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.lower.
+ lo_dword.hs_rss.pkt_info);
+#endif
/*
* Store the mbuf address into the next entry of the array
@@ -1024,6 +1124,10 @@ eth_igb_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
first_seg->ol_flags = pkt_flags;
+#ifdef RTE_NEXT_ABI
+ first_seg->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.
+ lower.lo_dword.hs_rss.pkt_info);
+#endif
/* Prefetch data of first segment, if configured to do so. */
rte_packet_prefetch((char *)first_seg->buf_addr +
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 09/19] cxgbe: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (7 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 08/19] fm10k: " Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 10/19] app/test-pipeline: " Helin Zhang
` (9 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be enabled
by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/cxgbe/sge.c | 8 ++++++++
1 file changed, 8 insertions(+)
v9 changes:
* Added unified packet type support in newly added cxgbe driver.
diff --git a/drivers/net/cxgbe/sge.c b/drivers/net/cxgbe/sge.c
index 359296e..fdae0b4 100644
--- a/drivers/net/cxgbe/sge.c
+++ b/drivers/net/cxgbe/sge.c
@@ -1326,14 +1326,22 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
mbuf->port = pkt->iff;
if (pkt->l2info & htonl(F_RXF_IP)) {
+#ifdef RTE_NEXT_ABI
+ mbuf->packet_type = RTE_PTYPE_L3_IPV4;
+#else
mbuf->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (unlikely(!csum_ok))
mbuf->ol_flags |= PKT_RX_IP_CKSUM_BAD;
if ((pkt->l2info & htonl(F_RXF_UDP | F_RXF_TCP)) && !csum_ok)
mbuf->ol_flags |= PKT_RX_L4_CKSUM_BAD;
} else if (pkt->l2info & htonl(F_RXF_IP6)) {
+#ifdef RTE_NEXT_ABI
+ mbuf->packet_type = RTE_PTYPE_L3_IPV6;
+#else
mbuf->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
}
mbuf->port = pkt->iff;
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 08/19] fm10k: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (6 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 07/19] vmxnet3: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 09/19] cxgbe: " Helin Zhang
` (10 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/fm10k/fm10k_rxtx.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
v4 changes:
* Supported unified packet type of fm10k from v4.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
v9 changes:
* Renamed MAC to ETHER in packet type names.
diff --git a/drivers/net/fm10k/fm10k_rxtx.c b/drivers/net/fm10k/fm10k_rxtx.c
index f5d1ad0..d3bcdca 100644
--- a/drivers/net/fm10k/fm10k_rxtx.c
+++ b/drivers/net/fm10k/fm10k_rxtx.c
@@ -68,12 +68,37 @@ static inline void dump_rxd(union fm10k_rx_desc *rxd)
static inline void
rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d)
{
+#ifdef RTE_NEXT_ABI
+ static const uint32_t
+ ptype_table[FM10K_RXD_PKTTYPE_MASK >> FM10K_RXD_PKTTYPE_SHIFT]
+ __rte_cache_aligned = {
+ [FM10K_PKTTYPE_OTHER] = RTE_PTYPE_L2_ETHER,
+ [FM10K_PKTTYPE_IPV4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4,
+ [FM10K_PKTTYPE_IPV4_EX] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [FM10K_PKTTYPE_IPV6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6,
+ [FM10K_PKTTYPE_IPV6_EX] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ };
+
+ m->packet_type = ptype_table[(d->w.pkt_info & FM10K_RXD_PKTTYPE_MASK)
+ >> FM10K_RXD_PKTTYPE_SHIFT];
+#else /* RTE_NEXT_ABI */
uint16_t ptype;
static const uint16_t pt_lut[] = { 0,
PKT_RX_IPV4_HDR, PKT_RX_IPV4_HDR_EXT,
PKT_RX_IPV6_HDR, PKT_RX_IPV6_HDR_EXT,
0, 0, 0
};
+#endif /* RTE_NEXT_ABI */
if (d->w.pkt_info & FM10K_RXD_RSSTYPE_MASK)
m->ol_flags |= PKT_RX_RSS_HASH;
@@ -97,9 +122,11 @@ rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d)
if (unlikely(d->d.staterr & FM10K_RXD_STATUS_RXE))
m->ol_flags |= PKT_RX_RECIP_ERR;
+#ifndef RTE_NEXT_ABI
ptype = (d->d.data & FM10K_RXD_PKTTYPE_MASK_L3) >>
FM10K_RXD_PKTTYPE_SHIFT;
m->ol_flags |= pt_lut[(uint8_t)ptype];
+#endif
}
uint16_t
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 05/19] i40e: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (3 preceding siblings ...)
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 04/19] ixgbe: " Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 06/19] enic: " Helin Zhang
` (13 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/i40e/i40e_rxtx.c | 554 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 554 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
v9 changes:
* Renamed MAC to ETHER in packet type names.
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index b2e1d6d..a608d1f 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -176,6 +176,540 @@ i40e_rxd_error_to_pkt_flags(uint64_t qword)
return flags;
}
+#ifdef RTE_NEXT_ABI
+/* For each value it means, datasheet of hardware can tell more details */
+static inline uint32_t
+i40e_rxd_pkt_type_mapping(uint8_t ptype)
+{
+ static const uint32_t ptype_table[UINT8_MAX] __rte_cache_aligned = {
+ /* L2 types */
+ /* [0] reserved */
+ [1] = RTE_PTYPE_L2_ETHER,
+ [2] = RTE_PTYPE_L2_ETHER_TIMESYNC,
+ /* [3] - [5] reserved */
+ [6] = RTE_PTYPE_L2_ETHER_LLDP,
+ /* [7] - [10] reserved */
+ [11] = RTE_PTYPE_L2_ETHER_ARP,
+ /* [12] - [21] reserved */
+
+ /* Non tunneled IPv4 */
+ [22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG,
+ [23] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG,
+ [24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP,
+ /* [25] reserved */
+ [26] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP,
+ [27] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP,
+ [28] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP,
+
+ /* IPv4 --> IPv4 */
+ [29] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [30] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [31] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [32] reserved */
+ [33] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [34] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [35] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> IPv6 */
+ [36] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [37] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [38] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [39] reserved */
+ [40] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [41] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [42] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN */
+ [43] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> IPv4 */
+ [44] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [45] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [46] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [47] reserved */
+ [48] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [49] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [50] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> IPv6 */
+ [51] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [52] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [53] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [54] reserved */
+ [55] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [56] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [57] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC */
+ [58] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */
+ [59] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [60] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [61] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [62] reserved */
+ [63] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [64] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [65] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */
+ [66] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [67] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [68] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [69] reserved */
+ [70] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [71] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [72] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN */
+ [73] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */
+ [74] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [75] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [76] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [77] reserved */
+ [78] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [79] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */
+ [81] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [82] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [83] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [84] reserved */
+ [85] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [86] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [87] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* Non tunneled IPv6 */
+ [88] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG,
+ [89] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG,
+ [90] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP,
+ /* [91] reserved */
+ [92] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP,
+ [93] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP,
+ [94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP,
+
+ /* IPv6 --> IPv4 */
+ [95] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [96] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [97] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [98] reserved */
+ [99] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [100] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [101] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> IPv6 */
+ [102] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [103] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [104] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [105] reserved */
+ [106] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [107] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [108] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN */
+ [109] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> IPv4 */
+ [110] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [111] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [112] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [113] reserved */
+ [114] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [115] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [116] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> IPv6 */
+ [117] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [118] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [119] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [120] reserved */
+ [121] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [122] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [123] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC */
+ [124] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */
+ [125] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [126] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [127] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [128] reserved */
+ [129] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [130] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [131] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */
+ [132] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [133] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [134] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [135] reserved */
+ [136] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [137] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [138] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN */
+ [139] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */
+ [140] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [141] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [142] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [143] reserved */
+ [144] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [145] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [146] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */
+ [147] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [148] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [149] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [150] reserved */
+ [151] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [152] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [153] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* All others reserved */
+ };
+
+ return ptype_table[ptype];
+}
+#else /* RTE_NEXT_ABI */
/* Translate pkt types to pkt flags */
static inline uint64_t
i40e_rxd_ptype_to_pkt_flags(uint64_t qword)
@@ -443,6 +977,7 @@ i40e_rxd_ptype_to_pkt_flags(uint64_t qword)
return ip_ptype_map[ptype];
}
+#endif /* RTE_NEXT_ABI */
#define I40E_RX_DESC_EXT_STATUS_FLEXBH_MASK 0x03
#define I40E_RX_DESC_EXT_STATUS_FLEXBH_FD_ID 0x01
@@ -730,11 +1265,18 @@ i40e_rx_scan_hw_ring(struct i40e_rx_queue *rxq)
i40e_rxd_to_vlan_tci(mb, &rxdp[j]);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ mb->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
mb->packet_type = (uint16_t)((qword1 &
I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
mb->hash.rss = rte_le_to_cpu_32(\
rxdp[j].wb.qword0.hi_dword.rss);
@@ -971,9 +1513,15 @@ i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
i40e_rxd_to_vlan_tci(rxm, &rxd);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
rxm->packet_type = (uint16_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
rxm->hash.rss =
rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss);
@@ -1129,10 +1677,16 @@ i40e_recv_scattered_pkts(void *rx_queue,
i40e_rxd_to_vlan_tci(first_seg, &rxd);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ first_seg->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
first_seg->packet_type = (uint16_t)((qword1 &
I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
rxm->hash.rss =
rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 07/19] vmxnet3: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (5 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 06/19] enic: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 08/19] fm10k: " Helin Zhang
` (11 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 ++++++++
1 file changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c b/drivers/net/vmxnet3/vmxnet3_rxtx.c
index a1eac45..25ae2f6 100644
--- a/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -649,9 +649,17 @@ vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
struct ipv4_hdr *ip = (struct ipv4_hdr *)(eth + 1);
if (((ip->version_ihl & 0xf) << 2) > (int)sizeof(struct ipv4_hdr))
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = RTE_PTYPE_L3_IPV4_EXT;
+#else
rxm->ol_flags |= PKT_RX_IPV4_HDR_EXT;
+#endif
else
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rxm->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!rcd->cnc) {
if (!rcd->ipc)
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 06/19] enic: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (4 preceding siblings ...)
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 05/19] i40e: " Helin Zhang
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 07/19] vmxnet3: " Helin Zhang
` (12 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/enic/enic_main.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 15313c2..f47e96c 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -423,7 +423,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
rx_pkt->pkt_len = bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD;
@@ -432,7 +436,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
} else {
/* Header split */
if (sop && !eop) {
@@ -445,7 +453,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
*rx_pkt_bucket = rx_pkt;
rx_pkt->pkt_len = bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
rx_pkt->ol_flags |=
@@ -457,13 +469,22 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
} else {
/* Payload */
hdr_rx_pkt = *rx_pkt_bucket;
hdr_rx_pkt->pkt_len += bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ hdr_rx_pkt->packet_type =
+ RTE_PTYPE_L3_IPV4;
+#else
hdr_rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
hdr_rx_pkt->ol_flags |=
@@ -475,7 +496,12 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ hdr_rx_pkt->packet_type =
+ RTE_PTYPE_L3_IPV6;
+#else
hdr_rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
}
}
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v9 04/19] ixgbe: replace bit mask based packet type with unified packet type
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
` (2 preceding siblings ...)
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 03/19] e1000: replace bit mask based packet type with unified packet type Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 05/19] i40e: " Helin Zhang
` (14 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
To unify packet type among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Note that around 2.5% performance drop (64B) was observed of doing
4 ports (1 port per 82599 card) IO forwarding on the same SNB core.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
v9 changes:
* Renamed MAC to ETHER in packet type names.
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index a211096..1455e54 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -860,6 +860,110 @@ end_of_tx:
* RX functions
*
**********************************************************************/
+#ifdef RTE_NEXT_ABI
+#define IXGBE_PACKET_TYPE_IPV4 0X01
+#define IXGBE_PACKET_TYPE_IPV4_TCP 0X11
+#define IXGBE_PACKET_TYPE_IPV4_UDP 0X21
+#define IXGBE_PACKET_TYPE_IPV4_SCTP 0X41
+#define IXGBE_PACKET_TYPE_IPV4_EXT 0X03
+#define IXGBE_PACKET_TYPE_IPV4_EXT_SCTP 0X43
+#define IXGBE_PACKET_TYPE_IPV6 0X04
+#define IXGBE_PACKET_TYPE_IPV6_TCP 0X14
+#define IXGBE_PACKET_TYPE_IPV6_UDP 0X24
+#define IXGBE_PACKET_TYPE_IPV6_EXT 0X0C
+#define IXGBE_PACKET_TYPE_IPV6_EXT_TCP 0X1C
+#define IXGBE_PACKET_TYPE_IPV6_EXT_UDP 0X2C
+#define IXGBE_PACKET_TYPE_IPV4_IPV6 0X05
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_TCP 0X15
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_UDP 0X25
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT 0X0D
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D
+#define IXGBE_PACKET_TYPE_MAX 0X80
+#define IXGBE_PACKET_TYPE_MASK 0X7F
+#define IXGBE_PACKET_TYPE_SHIFT 0X04
+static inline uint32_t
+ixgbe_rxd_pkt_info_to_pkt_type(uint16_t pkt_info)
+{
+ static const uint32_t
+ ptype_table[IXGBE_PACKET_TYPE_MAX] __rte_cache_aligned = {
+ [IXGBE_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4,
+ [IXGBE_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [IXGBE_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IXGBE_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ [IXGBE_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP,
+ [IXGBE_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER |
+ RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP,
+ };
+ if (unlikely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF))
+ return RTE_PTYPE_UNKNOWN;
+
+ pkt_info = (pkt_info >> IXGBE_PACKET_TYPE_SHIFT) &
+ IXGBE_PACKET_TYPE_MASK;
+
+ return ptype_table[pkt_info];
+}
+
+static inline uint64_t
+ixgbe_rxd_pkt_info_to_pkt_flags(uint16_t pkt_info)
+{
+ static uint64_t ip_rss_types_map[16] __rte_cache_aligned = {
+ 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH,
+ 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH,
+ PKT_RX_RSS_HASH, 0, 0, 0,
+ 0, 0, 0, PKT_RX_FDIR,
+ };
+#ifdef RTE_LIBRTE_IEEE1588
+ static uint64_t ip_pkt_etqf_map[8] = {
+ 0, 0, 0, PKT_RX_IEEE1588_PTP,
+ 0, 0, 0, 0,
+ };
+
+ if (likely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF))
+ return ip_pkt_etqf_map[(pkt_info >> 4) & 0X07] |
+ ip_rss_types_map[pkt_info & 0XF];
+ else
+ return ip_rss_types_map[pkt_info & 0XF];
+#else
+ return ip_rss_types_map[pkt_info & 0XF];
+#endif
+}
+#else /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
{
@@ -895,6 +999,7 @@ rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
#endif
return pkt_flags | ip_rss_types_map[hl_tp_rs & 0xF];
}
+#endif /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_status_to_pkt_flags(uint32_t rx_status)
@@ -950,7 +1055,13 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
struct rte_mbuf *mb;
uint16_t pkt_len;
uint64_t pkt_flags;
+#ifdef RTE_NEXT_ABI
+ int nb_dd;
+ uint32_t s[LOOK_AHEAD];
+ uint16_t pkt_info[LOOK_AHEAD];
+#else
int s[LOOK_AHEAD], nb_dd;
+#endif /* RTE_NEXT_ABI */
int i, j, nb_rx = 0;
@@ -973,6 +1084,12 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
for (j = LOOK_AHEAD-1; j >= 0; --j)
s[j] = rxdp[j].wb.upper.status_error;
+#ifdef RTE_NEXT_ABI
+ for (j = LOOK_AHEAD-1; j >= 0; --j)
+ pkt_info[j] = rxdp[j].wb.lower.lo_dword.
+ hs_rss.pkt_info;
+#endif /* RTE_NEXT_ABI */
+
/* Compute how many status bits were set */
nb_dd = 0;
for (j = 0; j < LOOK_AHEAD; ++j)
@@ -989,12 +1106,22 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].wb.upper.vlan);
/* convert descriptor fields to rte mbuf flags */
+#ifdef RTE_NEXT_ABI
+ pkt_flags = rx_desc_status_to_pkt_flags(s[j]);
+ pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
+ pkt_flags |=
+ ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]);
+ mb->ol_flags = pkt_flags;
+ mb->packet_type =
+ ixgbe_rxd_pkt_info_to_pkt_type(pkt_info[j]);
+#else /* RTE_NEXT_ABI */
pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(
rxdp[j].wb.lower.lo_dword.data);
/* reuse status field from scan list */
pkt_flags |= rx_desc_status_to_pkt_flags(s[j]);
pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
mb->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
mb->hash.rss = rxdp[j].wb.lower.hi_dword.rss;
@@ -1211,7 +1338,11 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
union ixgbe_adv_rx_desc rxd;
uint64_t dma_addr;
uint32_t staterr;
+#ifdef RTE_NEXT_ABI
+ uint32_t pkt_info;
+#else
uint32_t hlen_type_rss;
+#endif
uint16_t pkt_len;
uint16_t rx_id;
uint16_t nb_rx;
@@ -1329,6 +1460,19 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
rxm->data_len = pkt_len;
rxm->port = rxq->port_id;
+#ifdef RTE_NEXT_ABI
+ pkt_info = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.hs_rss.
+ pkt_info);
+ /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
+ rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
+
+ pkt_flags = rx_desc_status_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags |
+ ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info);
+ rxm->ol_flags = pkt_flags;
+ rxm->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info);
+#else /* RTE_NEXT_ABI */
hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data);
/* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
@@ -1337,6 +1481,7 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
rxm->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
rxm->hash.rss = rxd.wb.lower.hi_dword.rss;
@@ -1410,6 +1555,23 @@ ixgbe_fill_cluster_head_buf(
uint8_t port_id,
uint32_t staterr)
{
+#ifdef RTE_NEXT_ABI
+ uint16_t pkt_info;
+ uint64_t pkt_flags;
+
+ head->port = port_id;
+
+ /* The vlan_tci field is only valid when PKT_RX_VLAN_PKT is
+ * set in the pkt_flags field.
+ */
+ head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan);
+ pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.hs_rss.pkt_info);
+ pkt_flags = rx_desc_status_to_pkt_flags(staterr);
+ pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info);
+ head->ol_flags = pkt_flags;
+ head->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info);
+#else /* RTE_NEXT_ABI */
uint32_t hlen_type_rss;
uint64_t pkt_flags;
@@ -1425,6 +1587,7 @@ ixgbe_fill_cluster_head_buf(
pkt_flags |= rx_desc_status_to_pkt_flags(staterr);
pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
head->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
head->hash.rss = rte_le_to_cpu_32(desc->wb.lower.hi_dword.rss);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 02/19] mbuf: add definitions of unified packet types
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 01/19] mbuf: redefine packet_type in rte_mbuf Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 03/19] e1000: replace bit mask based packet type with unified packet type Helin Zhang
` (16 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
As there are only 6 bit flags in ol_flags for indicating packet
types, which is not enough to describe all the possible packet
types hardware can recognize. For example, i40e hardware can
recognize more than 150 packet types. Unified packet type is
composed of L2 type, L3 type, L4 type, tunnel type, inner L2 type,
inner L3 type and inner L4 type fields, and can be stored in
'struct rte_mbuf' of 32 bits field 'packet_type'.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_mbuf/rte_mbuf.h | 486 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 486 insertions(+)
v3 changes:
* Put the definitions of unified packet type into a single patch.
v4 changes:
* Added detailed description of each packet types.
v5 changes:
* Re-worded the commit logs.
* Added more detailed description for all packet types, together with examples.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
v9 changes:
* Renamed MAC to ETHER in packet type names.
* Corrected the packet type explanation of RTE_PTYPE_L2_ETHER.
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ac29da3..3a17d95 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -202,6 +202,492 @@ extern "C" {
/* Use final bit of flags to indicate a control mbuf */
#define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control data */
+#ifdef RTE_NEXT_ABI
+/*
+ * 32 bits are divided into several fields to mark packet types. Note that
+ * each field is indexical.
+ * - Bit 3:0 is for L2 types.
+ * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
+ * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
+ * - Bit 15:12 is for tunnel types.
+ * - Bit 19:16 is for inner L2 types.
+ * - Bit 23:20 is for inner L3 types.
+ * - Bit 27:24 is for inner L4 types.
+ * - Bit 31:28 is reserved.
+ *
+ * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT,
+ * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP
+ * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
+ *
+ * Note that L3 types values are selected for checking IPV4/IPV6 header from
+ * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and
+ * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
+ *
+ * Note that the packet types of the same packet recognized by different
+ * hardware may be different, as different hardware may have different
+ * capability of packet type recognition.
+ *
+ * examples:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=0x29
+ * | 'version'=6, 'next header'=0x3A
+ * | 'ICMPv6 header'>
+ * will be recognized on i40e hardware as packet type combination of,
+ * RTE_PTYPE_L2_ETHER |
+ * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ * RTE_PTYPE_TUNNEL_IP |
+ * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_INNER_L4_ICMP.
+ *
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x2F
+ * | 'GRE header'
+ * | 'version'=6, 'next header'=0x11
+ * | 'UDP header'>
+ * will be recognized on i40e hardware as packet type combination of,
+ * RTE_PTYPE_L2_ETHER |
+ * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_TUNNEL_GRENAT |
+ * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_INNER_L4_UDP.
+ */
+#define RTE_PTYPE_UNKNOWN 0x00000000
+/**
+ * Ethernet packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=[0x0800|0x86DD]>
+ */
+#define RTE_PTYPE_L2_ETHER 0x00000001
+/**
+ * Ethernet packet type for time sync.
+ *
+ * Packet format:
+ * <'ether type'=0x88F7>
+ */
+#define RTE_PTYPE_L2_ETHER_TIMESYNC 0x00000002
+/**
+ * ARP (Address Resolution Protocol) packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0806>
+ */
+#define RTE_PTYPE_L2_ETHER_ARP 0x00000003
+/**
+ * LLDP (Link Layer Discovery Protocol) packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x88CC>
+ */
+#define RTE_PTYPE_L2_ETHER_LLDP 0x00000004
+/**
+ * Mask of layer 2 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L2_MASK 0x0000000f
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and does not contain any
+ * header option.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=5>
+ */
+#define RTE_PTYPE_L3_IPV4 0x00000010
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and contains header
+ * options.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[6-15], 'options'>
+ */
+#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and does not contain any
+ * extension header.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x3B>
+ */
+#define RTE_PTYPE_L3_IPV6 0x00000040
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and may or maynot contain
+ * header options.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[5-15], <'options'>>
+ */
+#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and contains extension
+ * headers.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * 'extension headers'>
+ */
+#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and may or maynot contain
+ * extension headers.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * <'extension headers'>>
+ */
+#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
+/**
+ * Mask of layer 3 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L3_MASK 0x000000f0
+/**
+ * TCP (Transmission Control Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=6, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=6>
+ */
+#define RTE_PTYPE_L4_TCP 0x00000100
+/**
+ * UDP (User Datagram Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17>
+ */
+#define RTE_PTYPE_L4_UDP 0x00000200
+/**
+ * Fragmented IP (Internet Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * It refers to those packets of any IP types, which can be recognized as
+ * fragmented. A fragmented packet cannot be recognized as any other L4 types
+ * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP,
+ * RTE_PTYPE_L4_NONFRAG).
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'MF'=1>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=44>
+ */
+#define RTE_PTYPE_L4_FRAG 0x00000300
+/**
+ * SCTP (Stream Control Transmission Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=132, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=132>
+ */
+#define RTE_PTYPE_L4_SCTP 0x00000400
+/**
+ * ICMP (Internet Control Message Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=1, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=1>
+ */
+#define RTE_PTYPE_L4_ICMP 0x00000500
+/**
+ * Non-fragmented IP (Internet Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * It refers to those packets of any IP types, while cannot be recognized as
+ * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
+ * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'!=[6|17|44|132|1]>
+ */
+#define RTE_PTYPE_L4_NONFRAG 0x00000600
+/**
+ * Mask of layer 4 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L4_MASK 0x00000f00
+/**
+ * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=[4|41]>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[4|41]>
+ */
+#define RTE_PTYPE_TUNNEL_IP 0x00001000
+/**
+ * GRE (Generic Routing Encapsulation) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=47>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=47>
+ */
+#define RTE_PTYPE_TUNNEL_GRE 0x00002000
+/**
+ * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17
+ * | 'destination port'=4798>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17
+ * | 'destination port'=4798>
+ */
+#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
+/**
+ * NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling
+ * packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=47
+ * | 'protocol type'=0x6558>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=47
+ * | 'protocol type'=0x6558'>
+ */
+#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
+/**
+ * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17
+ * | 'destination port'=6081>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17
+ * | 'destination port'=6081>
+ */
+#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
+/**
+ * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area
+ * Network) or GRE (Generic Routing Encapsulation) could be recognized as this
+ * packet type, if they can not be recognized independently as of hardware
+ * capability.
+ */
+#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
+/**
+ * Mask of tunneling packet types.
+ */
+#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
+/**
+ * Ethernet packet type.
+ * It is used for inner packet type only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=[0x800|0x86DD]>
+ */
+#define RTE_PTYPE_INNER_L2_ETHER 0x00010000
+/**
+ * Ethernet packet type with VLAN (Virtual Local Area Network) tag.
+ *
+ * Packet format (inner only):
+ * <'ether type'=[0x800|0x86DD], vlan=[1-4095]>
+ */
+#define RTE_PTYPE_INNER_L2_ETHER_VLAN 0x00020000
+/**
+ * Mask of inner layer 2 packet types.
+ */
+#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and does not contain any header option.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=5>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and contains header options.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[6-15], 'options'>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and does not contain any extension header.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x3B>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and may or maynot contain header options.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[5-15], <'options'>>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and contains extension headers.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * 'extension headers'>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and may or maynot contain extension
+ * headers.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * <'extension headers'>>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
+/**
+ * Mask of inner layer 3 packet types.
+ */
+#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
+/**
+ * TCP (Transmission Control Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=6, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=6>
+ */
+#define RTE_PTYPE_INNER_L4_TCP 0x01000000
+/**
+ * UDP (User Datagram Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17>
+ */
+#define RTE_PTYPE_INNER_L4_UDP 0x02000000
+/**
+ * Fragmented IP (Internet Protocol) packet type.
+ * It is used for inner packet only, and may or maynot have layer 4 packet.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'MF'=1>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=44>
+ */
+#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
+/**
+ * SCTP (Stream Control Transmission Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=132, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=132>
+ */
+#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
+/**
+ * ICMP (Internet Control Message Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=1, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=1>
+ */
+#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
+/**
+ * Non-fragmented IP (Internet Protocol) packet type.
+ * It is used for inner packet only, and may or maynot have other unknown layer
+ * 4 packet types.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'!=[6|17|44|132|1]>
+ */
+#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
+/**
+ * Mask of inner layer 4 packet types.
+ */
+#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
+
+/**
+ * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
+ * one, bit 4 is selected to be used for IPv4 only. Then checking bit 4 can
+ * determin if it is an IPV4 packet.
+ */
+#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
+
+/**
+ * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
+ * one, bit 6 is selected to be used for IPv4 only. Then checking bit 6 can
+ * determin if it is an IPV4 packet.
+ */
+#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
+
+/* Check if it is a tunneling packet */
+#define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
+#endif /* RTE_NEXT_ABI */
+
/**
* Get the name of a RX offload flag
*
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 01/19] mbuf: redefine packet_type in rte_mbuf
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
@ 2015-07-03 8:32 3% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 02/19] mbuf: add definitions of unified packet types Helin Zhang
` (17 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
In order to unify the packet type, the field of 'packet_type' in 'struct rte_mbuf'
needs to be extended from 16 to 32 bits. Accordingly, some fields in 'struct rte_mbuf'
are re-organized to support this change for Vector PMD. As 'struct rte_kni_mbuf' for
KNI should be right mapped to 'struct rte_mbuf', it should be modified accordingly.
In ixgbe PMD driver, corresponding changes are added for the mbuf changes, especially
the bit masks of packet type for 'ol_flags' are replaced by unified packet type. In
addition, more packet types (UDP, TCP and SCTP) are supported in vectorized ixgbe PMD.
To avoid breaking ABI compatibility, all the changes would be enabled by RTE_NEXT_ABI,
which is disabled by default.
Note that around 2% performance drop (64B) was observed of doing 4 ports (1 port per
82599 card) IO forwarding on the same SNB core.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 +++++++++++++++++++++-
.../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 ++
lib/librte_mbuf/rte_mbuf.h | 26 ++++++++
3 files changed, 105 insertions(+), 2 deletions(-)
v2 changes:
* Enlarged the packet_type field from 16 bits to 32 bits.
* Redefined the packet type sub-fields.
* Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
v3 changes:
* Put the mbuf layout changes into a single patch.
* Disabled vector ixgbe PMD by default, as mbuf layout changed.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
* Integrated with changes of QinQ stripping/insertion.
v8 changes:
* Moved the field of 'vlan_tci_outer' in 'struct rte_mbuf' to the end
of the 1st cache line, to avoid breaking any vectorized PMD storing.
v9 changes:
* Put the mbuf changes and vector PMD changes together, as they are
tightly relevant.
diff --git a/drivers/net/ixgbe/ixgbe_rxtx_vec.c b/drivers/net/ixgbe/ixgbe_rxtx_vec.c
index abd10f6..ccea7cd 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx_vec.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx_vec.c
@@ -134,6 +134,12 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
*/
#ifdef RTE_IXGBE_RX_OLFLAGS_ENABLE
+#ifdef RTE_NEXT_ABI
+#define OLFLAGS_MASK_V (((uint64_t)PKT_RX_VLAN_PKT << 48) | \
+ ((uint64_t)PKT_RX_VLAN_PKT << 32) | \
+ ((uint64_t)PKT_RX_VLAN_PKT << 16) | \
+ ((uint64_t)PKT_RX_VLAN_PKT))
+#else
#define OLFLAGS_MASK ((uint16_t)(PKT_RX_VLAN_PKT | PKT_RX_IPV4_HDR |\
PKT_RX_IPV4_HDR_EXT | PKT_RX_IPV6_HDR |\
PKT_RX_IPV6_HDR_EXT))
@@ -142,11 +148,26 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
((uint64_t)OLFLAGS_MASK << 16) | \
((uint64_t)OLFLAGS_MASK))
#define PTYPE_SHIFT (1)
+#endif /* RTE_NEXT_ABI */
+
#define VTAG_SHIFT (3)
static inline void
desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
{
+#ifdef RTE_NEXT_ABI
+ __m128i vtag0, vtag1;
+ union {
+ uint16_t e[4];
+ uint64_t dword;
+ } vol;
+
+ vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]);
+ vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]);
+ vtag1 = _mm_unpacklo_epi32(vtag0, vtag1);
+ vtag1 = _mm_srli_epi16(vtag1, VTAG_SHIFT);
+ vol.dword = _mm_cvtsi128_si64(vtag1) & OLFLAGS_MASK_V;
+#else
__m128i ptype0, ptype1, vtag0, vtag1;
union {
uint16_t e[4];
@@ -166,6 +187,7 @@ desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
ptype1 = _mm_or_si128(ptype1, vtag1);
vol.dword = _mm_cvtsi128_si64(ptype1) & OLFLAGS_MASK_V;
+#endif /* RTE_NEXT_ABI */
rx_pkts[0]->ol_flags = vol.e[0];
rx_pkts[1]->ol_flags = vol.e[1];
@@ -196,6 +218,18 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
int pos;
uint64_t var;
__m128i shuf_msk;
+#ifdef RTE_NEXT_ABI
+ __m128i crc_adjust = _mm_set_epi16(
+ 0, 0, 0, /* ignore non-length fields */
+ -rxq->crc_len, /* sub crc on data_len */
+ 0, /* ignore high-16bits of pkt_len */
+ -rxq->crc_len, /* sub crc on pkt_len */
+ 0, 0 /* ignore pkt_type field */
+ );
+ __m128i dd_check, eop_check;
+ __m128i desc_mask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFF07F0);
+#else
__m128i crc_adjust = _mm_set_epi16(
0, 0, 0, 0, /* ignore non-length fields */
0, /* ignore high-16bits of pkt_len */
@@ -204,6 +238,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
0 /* ignore pkt_type field */
);
__m128i dd_check, eop_check;
+#endif /* RTE_NEXT_ABI */
if (unlikely(nb_pkts < RTE_IXGBE_VPMD_RX_BURST))
return 0;
@@ -232,6 +267,18 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
eop_check = _mm_set_epi64x(0x0000000200000002LL, 0x0000000200000002LL);
/* mask to shuffle from desc. to mbuf */
+#ifdef RTE_NEXT_ABI
+ shuf_msk = _mm_set_epi8(
+ 7, 6, 5, 4, /* octet 4~7, 32bits rss */
+ 15, 14, /* octet 14~15, low 16 bits vlan_macip */
+ 13, 12, /* octet 12~13, 16 bits data_len */
+ 0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */
+ 13, 12, /* octet 12~13, low 16 bits pkt_len */
+ 0xFF, 0xFF, /* skip high 16 bits pkt_type */
+ 1, /* octet 1, 8 bits pkt_type field */
+ 0 /* octet 0, 4 bits offset 4 pkt_type field */
+ );
+#else
shuf_msk = _mm_set_epi8(
7, 6, 5, 4, /* octet 4~7, 32bits rss */
0xFF, 0xFF, /* skip high 16 bits vlan_macip, zero out */
@@ -241,18 +288,28 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
13, 12, /* octet 12~13, 16 bits data_len */
0xFF, 0xFF /* skip pkt_type field */
);
+#endif /* RTE_NEXT_ABI */
/* Cache is empty -> need to scan the buffer rings, but first move
* the next 'n' mbufs into the cache */
sw_ring = &rxq->sw_ring[rxq->rx_tail];
- /*
- * A. load 4 packet in one loop
+#ifdef RTE_NEXT_ABI
+ /* A. load 4 packet in one loop
+ * [A*. mask out 4 unused dirty field in desc]
* B. copy 4 mbuf point from swring to rx_pkts
* C. calc the number of DD bits among the 4 packets
* [C*. extract the end-of-packet bit, if requested]
* D. fill info. from desc to mbuf
*/
+#else
+ /* A. load 4 packet in one loop
+ * B. copy 4 mbuf point from swring to rx_pkts
+ * C. calc the number of DD bits among the 4 packets
+ * [C*. extract the end-of-packet bit, if requested]
+ * D. fill info. from desc to mbuf
+ */
+#endif /* RTE_NEXT_ABI */
for (pos = 0, nb_pkts_recd = 0; pos < RTE_IXGBE_VPMD_RX_BURST;
pos += RTE_IXGBE_DESCS_PER_LOOP,
rxdp += RTE_IXGBE_DESCS_PER_LOOP) {
@@ -289,6 +346,16 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
/* B.2 copy 2 mbuf point into rx_pkts */
_mm_storeu_si128((__m128i *)&rx_pkts[pos+2], mbp2);
+#ifdef RTE_NEXT_ABI
+ /* A* mask out 0~3 bits RSS type */
+ descs[3] = _mm_and_si128(descs[3], desc_mask);
+ descs[2] = _mm_and_si128(descs[2], desc_mask);
+
+ /* A* mask out 0~3 bits RSS type */
+ descs[1] = _mm_and_si128(descs[1], desc_mask);
+ descs[0] = _mm_and_si128(descs[0], desc_mask);
+#endif /* RTE_NEXT_ABI */
+
/* avoid compiler reorder optimization */
rte_compiler_barrier();
@@ -301,7 +368,11 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
/* C.1 4=>2 filter staterr info only */
sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]);
+#ifdef RTE_NEXT_ABI
+ /* set ol_flags with vlan packet type */
+#else
/* set ol_flags with packet type and vlan tag */
+#endif /* RTE_NEXT_ABI */
desc_to_olflags_v(descs, &rx_pkts[pos]);
/* D.2 pkt 3,4 set in_port/nb_seg and remove crc */
diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
index 1e55c2d..e9f38bd 100644
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
@@ -117,9 +117,15 @@ struct rte_kni_mbuf {
uint16_t data_off; /**< Start address of data in segment buffer. */
char pad1[4];
uint64_t ol_flags; /**< Offload features. */
+#ifdef RTE_NEXT_ABI
+ char pad2[4];
+ uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
+ uint16_t data_len; /**< Amount of data in segment buffer. */
+#else
char pad2[2];
uint16_t data_len; /**< Amount of data in segment buffer. */
uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
+#endif
/* fields on second cache line */
char pad3[8] __attribute__((__aligned__(RTE_CACHE_LINE_SIZE)));
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 80419df..ac29da3 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -276,6 +276,28 @@ struct rte_mbuf {
/* remaining bytes are set on RX when pulling packet from descriptor */
MARKER rx_descriptor_fields1;
+#ifdef RTE_NEXT_ABI
+ /*
+ * The packet type, which is the combination of outer/inner L2, L3, L4
+ * and tunnel types.
+ */
+ union {
+ uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */
+ struct {
+ uint32_t l2_type:4; /**< (Outer) L2 type. */
+ uint32_t l3_type:4; /**< (Outer) L3 type. */
+ uint32_t l4_type:4; /**< (Outer) L4 type. */
+ uint32_t tun_type:4; /**< Tunnel type. */
+ uint32_t inner_l2_type:4; /**< Inner L2 type. */
+ uint32_t inner_l3_type:4; /**< Inner L3 type. */
+ uint32_t inner_l4_type:4; /**< Inner L4 type. */
+ };
+ };
+
+ uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
+ uint16_t data_len; /**< Amount of data in segment buffer. */
+ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
+#else /* RTE_NEXT_ABI */
/**
* The packet type, which is used to indicate ordinary packet and also
* tunneled packet format, i.e. each number is represented a type of
@@ -287,6 +309,7 @@ struct rte_mbuf {
uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */
+#endif /* RTE_NEXT_ABI */
union {
uint32_t rss; /**< RSS hash result if RSS enabled */
struct {
@@ -307,6 +330,9 @@ struct rte_mbuf {
} hash; /**< hash information */
uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */
+#ifdef RTE_NEXT_ABI
+ uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */
+#endif /* RTE_NEXT_ABI */
/* second cache line - fields only used in slow path or on TX */
MARKER cacheline1 __rte_cache_aligned;
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v9 00/19] unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (18 preceding siblings ...)
2015-06-23 16:13 0% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Ananyev, Konstantin
@ 2015-07-03 8:32 4% ` Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 01/19] mbuf: redefine packet_type in rte_mbuf Helin Zhang
` (18 more replies)
19 siblings, 19 replies; 200+ results
From: Helin Zhang @ 2015-07-03 8:32 UTC (permalink / raw)
To: dev
Currently only 6 bits which are stored in ol_flags are used to indicate the
packet types. This is not enough, as some NIC hardware can recognize quite
a lot of packet types, e.g i40e hardware can recognize more than 150 packet
types. Hiding those packet types hides hardware offload capabilities which
could be quite useful for improving performance and for end users.
So an unified packet types are needed to support all possible PMDs. A 16 bits
packet_type in mbuf structure can be changed to 32 bits and used for this
purpose. In addition, all packet types stored in ol_flag field should be
deleted at all, and 6 bits of ol_flags can be save as the benifit.
Initially, 32 bits of packet_type can be divided into several sub fields to
indicate different packet type information of a packet. The initial design
is to divide those bits into fields for L2 types, L3 types, L4 types, tunnel
types, inner L2 types, inner L3 types and inner L4 types. All PMDs should
translate the offloaded packet types into these 7 fields of information, for
user applications.
To avoid breaking ABI compatibility, currently all the code changes for
unified packet type are disabled at compile time by default. Users can enable
it manually by defining the macro of RTE_NEXT_ABI. The code changes will be
valid by default in a future release, and the old version will be deleted
accordingly, after the ABI change process is done.
Note that this patch set should be integrated after another patch set for
'[PATCH v3 0/7] support i40e QinQ stripping and insertion', to clearly solve
the conflict during integration. As both patch sets modified 'struct rte_mbuf',
and the final layout of the 'struct rte_mbuf' is key to vectorized ixgbe PMD.
Its v8 version was acked by Konstantin Ananyev <konstantin.ananyev@intel.com>
v2 changes:
* Enlarged the packet_type field from 16 bits to 32 bits.
* Redefined the packet type sub-fields.
* Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
* Used redefined packet types and enlarged packet_type field for all PMDs
and corresponding applications.
* Removed changes in bond and its relevant application, as there is no need
at all according to the recent bond changes.
v3 changes:
* Put the mbuf layout changes into a single patch.
* Put vector ixgbe changes right after mbuf changes.
* Disabled vector ixgbe PMD by default, as mbuf layout changed, and then
re-enabled it after vector ixgbe PMD updated.
* Put the definitions of unified packet type into a single patch.
* Minor bug fixes and enhancements in l3fwd example.
v4 changes:
* Added detailed description of each packet types.
* Supported unified packet type of fm10k.
* Added printing logs of packet types of each received packet for rxonly
mode in testpmd.
* Removed several useless code lines which block packet type unification from
app/test/packet_burst_generator.c.
v5 changes:
* Added more detailed description for each packet types, together with examples.
* Rolled back the macro definitions of RX packet flags, for ABI compitability.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
* Integrated with patch set for '[PATCH v3 0/7] support i40e QinQ stripping
and insertion', to clearly solve the conflicts during merging.
v8 changes:
* Moved the field of 'vlan_tci_outer' in 'struct rte_mbuf' to the end of the 1st
cache line, to avoid breaking any vectorized PMD storing, as fields of
'packet_type, pkt_len, data_len, vlan_tci, rss' should be in an contiguous 128
bits.
v9 changes:
* Put the mbuf changes and vector PMD changes together, as they are
tightly relevant.
* Renamed MAC to ETHER in packet type names.
* Corrected the packet type explanation of RTE_PTYPE_L2_ETHER.
* Reworked newly added cxgbe driver and tep_termination example application to
support unified packet type, which is disabled by default.
Helin Zhang (19):
mbuf: redefine packet_type in rte_mbuf
mbuf: add definitions of unified packet types
e1000: replace bit mask based packet type with unified packet type
ixgbe: replace bit mask based packet type with unified packet type
i40e: replace bit mask based packet type with unified packet type
enic: replace bit mask based packet type with unified packet type
vmxnet3: replace bit mask based packet type with unified packet type
fm10k: replace bit mask based packet type with unified packet type
cxgbe: replace bit mask based packet type with unified packet type
app/test-pipeline: replace bit mask based packet type with unified
packet type
app/testpmd: replace bit mask based packet type with unified packet
type
app/test: Remove useless code
examples/ip_fragmentation: replace bit mask based packet type with
unified packet type
examples/ip_reassembly: replace bit mask based packet type with
unified packet type
examples/l3fwd-acl: replace bit mask based packet type with unified
packet type
examples/l3fwd-power: replace bit mask based packet type with unified
packet type
examples/l3fwd: replace bit mask based packet type with unified packet
type
examples/tep_termination: replace bit mask based packet type with
unified packet type
mbuf: remove old packet type bit masks
app/test-pipeline/pipeline_hash.c | 13 +
app/test-pmd/csumonly.c | 14 +
app/test-pmd/rxonly.c | 183 +++++++
app/test/packet_burst_generator.c | 6 +-
drivers/net/cxgbe/sge.c | 8 +
drivers/net/e1000/igb_rxtx.c | 104 ++++
drivers/net/enic/enic_main.c | 26 +
drivers/net/fm10k/fm10k_rxtx.c | 27 +
drivers/net/i40e/i40e_rxtx.c | 554 +++++++++++++++++++++
drivers/net/ixgbe/ixgbe_rxtx.c | 163 ++++++
drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 ++-
drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 +
examples/ip_fragmentation/main.c | 9 +
examples/ip_reassembly/main.c | 9 +
examples/l3fwd-acl/main.c | 29 +-
examples/l3fwd-power/main.c | 8 +
examples/l3fwd/main.c | 123 ++++-
examples/tep_termination/vxlan.c | 4 +
.../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 +
lib/librte_mbuf/rte_mbuf.c | 4 +
lib/librte_mbuf/rte_mbuf.h | 516 +++++++++++++++++++
21 files changed, 1876 insertions(+), 13 deletions(-)
--
1.9.3
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v3 0/7] ethdev: add support for ieee1588 timestamping
2015-07-02 15:16 4% ` [dpdk-dev] [PATCH v3 " John McNamara
2015-07-02 15:16 14% ` [dpdk-dev] [PATCH v3 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
@ 2015-07-03 8:22 0% ` Lu, Wenzhuo
1 sibling, 0 replies; 200+ results
From: Lu, Wenzhuo @ 2015-07-03 8:22 UTC (permalink / raw)
To: Mcnamara, John, dev
Hi,
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of John McNamara
> Sent: Thursday, July 2, 2015 11:16 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v3 0/7] ethdev: add support for ieee1588
> timestamping
>
> This patchset adds ethdev API to enable and read IEEE1588/802.1AS PTP
> timestamps from devices that support it. The following functions are added:
>
> rte_eth_timesync_enable()
> rte_eth_timesync_disable()
> rte_eth_timesync_read_rx_timestamp()
> rte_eth_timesync_read_tx_timestamp()
>
> The "ieee1588" forwarding mode in testpmd is also refactored to demonstrate
> the new API and to clean up the code.
>
> Adds support for igb, ixgbe and i40e.
>
> V3:
> * Fixed issued with version.map.
>
> V2:
> * Added i40e support.
>
> * Renamed ethdev functions from rte_eth_ieee15888_*() to
> rte_eth_timesync_*()
> since 802.1AS can be supported through the same interfaces.
>
> V1:
> * Initial version for
>
>
> John McNamara (7):
> ethdev: add support for ieee1588 timestamping
> e1000: add support for ieee1588 timestamping
> ixgbe: add support for ieee1588 timestamping
> i40e: add support for ieee1588 timestamping
> app/testpmd: refactor ieee1588 forwarding
> doc: document ieee1588 forwarding mode
> abi: announce mbuf addition for ieee1588 in DPDK 2.2
>
> app/test-pmd/ieee1588fwd.c | 466 ++--------------------------
> doc/guides/rel_notes/abi.rst | 5 +
> doc/guides/testpmd_app_ug/run_app.rst | 2 +-
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 2 +
> drivers/net/e1000/igb_ethdev.c | 115 +++++++
> drivers/net/i40e/i40e_ethdev.c | 143 +++++++++
> drivers/net/i40e/i40e_rxtx.c | 39 ++-
> drivers/net/ixgbe/ixgbe_ethdev.c | 122 ++++++++
> lib/librte_ether/rte_ethdev.c | 70 ++++-
> lib/librte_ether/rte_ethdev.h | 90 +++++-
> lib/librte_ether/rte_ether_version.map | 4 +
> 11 files changed, 615 insertions(+), 443 deletions(-)
>
> --
> 1.8.1.4
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types
2015-07-02 9:31 0% ` Olivier MATZ
@ 2015-07-03 1:30 0% ` Zhang, Helin
0 siblings, 0 replies; 200+ results
From: Zhang, Helin @ 2015-07-03 1:30 UTC (permalink / raw)
To: Olivier MATZ, dev
> -----Original Message-----
> From: Olivier MATZ [mailto:olivier.matz@6wind.com]
> Sent: Thursday, July 2, 2015 5:32 PM
> To: Zhang, Helin; dev@dpdk.org
> Cc: Cao, Waterman; Liang, Cunming; Liu, Jijiang; Ananyev, Konstantin; Richardson,
> Bruce; yongwang@vmware.com; Wu, Jingjing
> Subject: Re: [PATCH v8 03/18] mbuf: add definitions of unified packet types
>
> Hi Helin,
>
> On 07/02/2015 03:30 AM, Zhang, Helin wrote:
> > Hi Oliver
> >
> > Thanks for your helps!
> >
> >> -----Original Message-----
> >> From: Olivier MATZ [mailto:olivier.matz@6wind.com]
> >> Sent: Tuesday, June 30, 2015 4:44 PM
> >> To: Zhang, Helin; dev@dpdk.org
> >> Cc: Cao, Waterman; Liang, Cunming; Liu, Jijiang; Ananyev, Konstantin;
> >> Richardson, Bruce; yongwang@vmware.com; Wu, Jingjing
> >> Subject: Re: [PATCH v8 03/18] mbuf: add definitions of unified packet
> >> types
> >>
> >> Hi Helin,
> >>
> >> This is greatly documented, thanks!
> >> Please find a small comment below.
> >>
> >> On 06/23/2015 03:50 AM, Helin Zhang wrote:
> >>> As there are only 6 bit flags in ol_flags for indicating packet
> >>> types, which is not enough to describe all the possible packet types
> >>> hardware can recognize. For example, i40e hardware can recognize
> >>> more than 150 packet types. Unified packet type is composed of L2
> >>> type, L3 type, L4 type, tunnel type, inner L2 type, inner L3 type
> >>> and inner L4 type fields, and can be stored in 'struct rte_mbuf' of
> >>> 32 bits field 'packet_type'.
> >>> To avoid breaking ABI compatibility, all the changes would be
> >>> enabled by RTE_NEXT_ABI, which is disabled by default.
> >>>
> >>> [...]
> >>> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> >>> index 0315561..0ee0c55 100644
> >>> --- a/lib/librte_mbuf/rte_mbuf.h
> >>> +++ b/lib/librte_mbuf/rte_mbuf.h
> >>> @@ -201,6 +201,493 @@ extern "C" {
> >>> /* Use final bit of flags to indicate a control mbuf */
> >>> #define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains
> control
> >> data */
> >>>
> >>> +#ifdef RTE_NEXT_ABI
> >>> +/*
> >>> + * 32 bits are divided into several fields to mark packet types.
> >>> +Note that
> >>> + * each field is indexical.
> >>> + * - Bit 3:0 is for L2 types.
> >>> + * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
> >>> + * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
> >>> + * - Bit 15:12 is for tunnel types.
> >>> + * - Bit 19:16 is for inner L2 types.
> >>> + * - Bit 23:20 is for inner L3 types.
> >>> + * - Bit 27:24 is for inner L4 types.
> >>> + * - Bit 31:28 is reserved.
> >>> + *
> >>> + * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4,
> >>> +RTE_PTYPE_L3_IPV4_EXT,
> >>> + * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP,
> >>> +RTE_PTYPE_L4_UDP
> >>> + * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
> >>> + *
> >>> + * Note that L3 types values are selected for checking IPV4/IPV6
> >>> +header from
> >>> + * performance point of view. Reading annotations of
> >>> +RTE_ETH_IS_IPV4_HDR and
> >>> + * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type
> values.
> >>> + *
> >>> + * Note that the packet types of the same packet recognized by
> >>> +different
> >>> + * hardware may be different, as different hardware may have
> >>> +different
> >>> + * capability of packet type recognition.
> >>> + *
> >>> + * examples:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=0x29
> >>> + * | 'version'=6, 'next header'=0x3A
> >>> + * | 'ICMPv6 header'>
> >>> + * will be recognized on i40e hardware as packet type combination
> >>> +of,
> >>> + * RTE_PTYPE_L2_MAC |
> >>> + * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
> >>> + * RTE_PTYPE_TUNNEL_IP |
> >>> + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
> >>> + * RTE_PTYPE_INNER_L4_ICMP.
> >>> + *
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=0x2F
> >>> + * | 'GRE header'
> >>> + * | 'version'=6, 'next header'=0x11
> >>> + * | 'UDP header'>
> >>> + * will be recognized on i40e hardware as packet type combination
> >>> +of,
> >>> + * RTE_PTYPE_L2_MAC |
> >>> + * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
> >>> + * RTE_PTYPE_TUNNEL_GRENAT |
> >>> + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
> >>> + * RTE_PTYPE_INNER_L4_UDP.
> >>> + */
> >>> +#define RTE_PTYPE_UNKNOWN 0x00000000
> >>> +/**
> >>> + * MAC (Media Access Control) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=[0x0800|0x86DD|others]> */
> >>> +#define RTE_PTYPE_L2_MAC 0x00000001
> >>
> >> I'm wondering if RTE_PTYPE_L2_ETHER is not a better name?
> > Ethernet includes both Data Link Layer and Physical Layer, while MAC
> > is for Data Link Layer only. I would prefer to keep 'MAC' in the names, rather
> than 'ether'.
> > Any opinions from others?
>
> Just to precise what I'm saying: MAC is the interface between the logical link and
> the physical layer. It is different depending on the physical media (Ethernet,
> Token Ring, WLAN, ...).
> Every packet has a MAC layer and I think "MAC" does not bring any information.
>
> Having "ETHER" in the name would inform the software that it can expect an
> ethernet header. In the future, I would expect to have more L2 types like PPP.
OK, good explanation! I will change the name and thanks!
>
> I also have another question about RTE_PTYPE_L2_MAC. You describe it as
> "<'ether type'=[0x0800|0x86DD|others]>".
> What is the meaning of "others"? Does it mean that it is valid to set
> RTE_PTYPE_L2_MAC for any received packet?
OK. I think others should be removed. As ARP/LLDP like packet types are combined
together with MAC type.
>
> For instance, an ARP packet. The driver has the choice to set:
> A- RTE_PTYPE_UNKNOWN: the driver does not know the L2 packet
> type
> B- RTE_PTYPE_L2_MAC: the driver knows it's an ethernet packet
> (it should be the case for all received packets today as
> dpdk only supports ethernet ports)
> C- RTE_PTYPE_L2_ARP: the driver knows that the packet carries
> an ARP header after the ethernet header.
>
> Is it correct for a driver to always set B- for all received packets?
Currently it combines ether type and other ether type based protocols together.
So if it is a L2_LLDP, it could be treated as MAC + LLDP, while MAC means MAC only or MAC + L3.
>
> Another thing that bothers me a bit is that L2_ARP, L2_LLDP, L2_MAC_TIMESYNC,
> (...) are not really L2 types. The L2 type is Ethernet. On the other hand, they are
> not L3 type either.
> So, I have no other solution. The OSI model is probably a bit too theorical, and we
> have to choose the solution that is the most useful for the applications, even if it
> does not absolutely matches the theory ;)
Yes, they are a bit bothering. Currently they are combined together with L2 types.
Maybe it needs to define a MISC PACKET TYPE field, as we still have 4 bits available there.
Thanks,
Helin
>
>
> Regards,
> Olivier
>
>
> >
> > Regards,
> > Helin
> >
> >>
> >>
> >>> +/**
> >>> + * MAC (Media Access Control) packet type for time sync.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x88F7>
> >>> + */
> >>> +#define RTE_PTYPE_L2_MAC_TIMESYNC 0x00000002
> >>> +/**
> >>> + * ARP (Address Resolution Protocol) packet type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0806>
> >>> + */
> >>> +#define RTE_PTYPE_L2_ARP 0x00000003
> >>> +/**
> >>> + * LLDP (Link Layer Discovery Protocol) packet type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x88CC>
> >>> + */
> >>> +#define RTE_PTYPE_L2_LLDP 0x00000004
> >>
> >> Maybe ETHER should appear in these names too, what do you think?
> > Same as above.
> >
> >>
> >>
> >>
> >>
> >>> +/**
> >>> + * Mask of layer 2 packet types.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + */
> >>> +#define RTE_PTYPE_L2_MASK 0x0000000f
> >>> +/**
> >>> + * IP (Internet Protocol) version 4 packet type.
> >>> + * It is used for outer packet for tunneling cases, and does not
> >>> +contain any
> >>> + * header option.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'ihl'=5>
> >>> + */
> >>> +#define RTE_PTYPE_L3_IPV4 0x00000010
> >>> +/**
> >>> + * IP (Internet Protocol) version 4 packet type.
> >>> + * It is used for outer packet for tunneling cases, and contains
> >>> +header
> >>> + * options.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'ihl'=[6-15], 'options'> */
> >>> +#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
> >>> +/**
> >>> + * IP (Internet Protocol) version 6 packet type.
> >>> + * It is used for outer packet for tunneling cases, and does not
> >>> +contain any
> >>> + * extension header.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=0x3B> */
> >>> +#define RTE_PTYPE_L3_IPV6 0x00000040
> >>> +/**
> >>> + * IP (Internet Protocol) version 4 packet type.
> >>> + * It is used for outer packet for tunneling cases, and may or
> >>> +maynot contain
> >>> + * header options.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'ihl'=[5-15], <'options'>> */
> >>> +#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
> >>> +/**
> >>> + * IP (Internet Protocol) version 6 packet type.
> >>> + * It is used for outer packet for tunneling cases, and contains
> >>> +extension
> >>> + * headers.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> >>> + * 'extension headers'>
> >>> + */
> >>> +#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
> >>> +/**
> >>> + * IP (Internet Protocol) version 6 packet type.
> >>> + * It is used for outer packet for tunneling cases, and may or
> >>> +maynot contain
> >>> + * extension headers.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next
> header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> >>> + * <'extension headers'>>
> >>> + */
> >>> +#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
> >>> +/**
> >>> + * Mask of layer 3 packet types.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + */
> >>> +#define RTE_PTYPE_L3_MASK 0x000000f0
> >>> +/**
> >>> + * TCP (Transmission Control Protocol) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=6, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=6>
> >>> + */
> >>> +#define RTE_PTYPE_L4_TCP 0x00000100
> >>> +/**
> >>> + * UDP (User Datagram Protocol) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=17, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=17> */
> >>> +#define RTE_PTYPE_L4_UDP 0x00000200
> >>> +/**
> >>> + * Fragmented IP (Internet Protocol) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * It refers to those packets of any IP types, which can be
> >>> +recognized as
> >>> + * fragmented. A fragmented packet cannot be recognized as any
> >>> +other
> >>> +L4 types
> >>> + * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP,
> >>> +RTE_PTYPE_L4_ICMP,
> >>> + * RTE_PTYPE_L4_NONFRAG).
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'MF'=1>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=44> */
> >>> +#define RTE_PTYPE_L4_FRAG 0x00000300
> >>> +/**
> >>> + * SCTP (Stream Control Transmission Protocol) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=132, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=132> */
> >>> +#define RTE_PTYPE_L4_SCTP 0x00000400
> >>> +/**
> >>> + * ICMP (Internet Control Message Protocol) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=1, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=1>
> >>> + */
> >>> +#define RTE_PTYPE_L4_ICMP 0x00000500
> >>> +/**
> >>> + * Non-fragmented IP (Internet Protocol) packet type.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + *
> >>> + * It refers to those packets of any IP types, while cannot be
> >>> +recognized as
> >>> + * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
> >>> + * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'!=[6|17|44|132|1]> */
> >>> +#define RTE_PTYPE_L4_NONFRAG 0x00000600
> >>> +/**
> >>> + * Mask of layer 4 packet types.
> >>> + * It is used for outer packet for tunneling cases.
> >>> + */
> >>> +#define RTE_PTYPE_L4_MASK 0x00000f00
> >>> +/**
> >>> + * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=[4|41]>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=[4|41]> */
> >>> +#define RTE_PTYPE_TUNNEL_IP 0x00001000
> >>> +/**
> >>> + * GRE (Generic Routing Encapsulation) tunneling packet type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=47>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=47> */
> >>> +#define RTE_PTYPE_TUNNEL_GRE 0x00002000
> >>> +/**
> >>> + * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=17
> >>> + * | 'destination port'=4798>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=17
> >>> + * | 'destination port'=4798>
> >>> + */
> >>> +#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
> >>> +/**
> >>> + * NVGRE (Network Virtualization using Generic Routing
> >>> +Encapsulation) tunneling
> >>> + * packet type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=47
> >>> + * | 'protocol type'=0x6558>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=47
> >>> + * | 'protocol type'=0x6558'>
> >>> + */
> >>> +#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
> >>> +/**
> >>> + * GENEVE (Generic Network Virtualization Encapsulation) tunneling
> >>> +packet
> >> type.
> >>> + *
> >>> + * Packet format:
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=17
> >>> + * | 'destination port'=6081>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=17
> >>> + * | 'destination port'=6081>
> >>> + */
> >>> +#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
> >>> +/**
> >>> + * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local
> >>> +Area
> >>> + * Network) or GRE (Generic Routing Encapsulation) could be
> >>> +recognized as this
> >>> + * packet type, if they can not be recognized independently as of
> >>> +hardware
> >>> + * capability.
> >>> + */
> >>> +#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
> >>> +/**
> >>> + * Mask of tunneling packet types.
> >>> + */
> >>> +#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
> >>> +/**
> >>> + * MAC (Media Access Control) packet type.
> >>> + * It is used for inner packet type only.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=[0x800|0x86DD]>
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L2_MAC 0x00010000
> >>> +/**
> >>> + * MAC (Media Access Control) packet type with VLAN (Virtual Local
> >>> +Area
> >>> + * Network) tag.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=[0x800|0x86DD], vlan=[1-4095]> */
> >>> +#define RTE_PTYPE_INNER_L2_MAC_VLAN 0x00020000
> >>> +/**
> >>> + * Mask of inner layer 2 packet types.
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
> >>> +/**
> >>> + * IP (Internet Protocol) version 4 packet type.
> >>> + * It is used for inner packet only, and does not contain any header option.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'ihl'=5>
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
> >>> +/**
> >>> + * IP (Internet Protocol) version 4 packet type.
> >>> + * It is used for inner packet only, and contains header options.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'ihl'=[6-15], 'options'> */
> >>> +#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
> >>> +/**
> >>> + * IP (Internet Protocol) version 6 packet type.
> >>> + * It is used for inner packet only, and does not contain any extension
> header.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=0x3B> */
> >>> +#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
> >>> +/**
> >>> + * IP (Internet Protocol) version 4 packet type.
> >>> + * It is used for inner packet only, and may or maynot contain header
> options.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'ihl'=[5-15], <'options'>> */ #define
> >>> +RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
> >>> +/**
> >>> + * IP (Internet Protocol) version 6 packet type.
> >>> + * It is used for inner packet only, and contains extension headers.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> >>> + * 'extension headers'>
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
> >>> +/**
> >>> + * IP (Internet Protocol) version 6 packet type.
> >>> + * It is used for inner packet only, and may or maynot contain
> >>> +extension
> >>> + * headers.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next
> header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> >>> + * <'extension headers'>>
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
> >>> +/**
> >>> + * Mask of inner layer 3 packet types.
> >>> + */
> >>> +#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
> >>> +/**
> >>> + * TCP (Transmission Control Protocol) packet type.
> >>> + * It is used for inner packet only.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=6, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=6>
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L4_TCP 0x01000000
> >>> +/**
> >>> + * UDP (User Datagram Protocol) packet type.
> >>> + * It is used for inner packet only.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=17, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=17> */
> >>> +#define RTE_PTYPE_INNER_L4_UDP 0x02000000
> >>> +/**
> >>> + * Fragmented IP (Internet Protocol) packet type.
> >>> + * It is used for inner packet only, and may or maynot have layer 4 packet.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'MF'=1>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=44> */
> >>> +#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
> >>> +/**
> >>> + * SCTP (Stream Control Transmission Protocol) packet type.
> >>> + * It is used for inner packet only.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=132, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=132> */
> >>> +#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
> >>> +/**
> >>> + * ICMP (Internet Control Message Protocol) packet type.
> >>> + * It is used for inner packet only.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'=1, 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'=1>
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
> >>> +/**
> >>> + * Non-fragmented IP (Internet Protocol) packet type.
> >>> + * It is used for inner packet only, and may or maynot have other
> >>> +unknown layer
> >>> + * 4 packet types.
> >>> + *
> >>> + * Packet format (inner only):
> >>> + * <'ether type'=0x0800
> >>> + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
> >>> + * or,
> >>> + * <'ether type'=0x86DD
> >>> + * | 'version'=6, 'next header'!=[6|17|44|132|1]> */
> >>> +#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
> >>> +/**
> >>> + * Mask of inner layer 4 packet types.
> >>> + */
> >>> +#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
> >>> +
> >>> +/**
> >>> + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4
> >>> +types one by
> >>> + * one, bit 4 is selected to be used for IPv4 only. Then checking
> >>> +bit
> >>> +4 can
> >>> + * determin if it is an IPV4 packet.
> >>> + */
> >>> +#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
> >>> +
> >>> +/**
> >>> + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4
> >>> +types one by
> >>> + * one, bit 6 is selected to be used for IPv4 only. Then checking
> >>> +bit
> >>> +6 can
> >>> + * determin if it is an IPV4 packet.
> >>> + */
> >>> +#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
> >>> +
> >>> +/* Check if it is a tunneling packet */ #define
> >>> +RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
> >> #endif
> >>> +/* RTE_NEXT_ABI */
> >>> +
> >>> /**
> >>> * Get the name of a RX offload flag
> >>> *
> >>>
> >
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH] mk: enable next abi in static libs
@ 2015-07-02 22:05 20% Thomas Monjalon
2015-07-06 13:18 4% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-07-02 22:05 UTC (permalink / raw)
To: dev
When a change makes really hard to keep ABI compatibility,
instead of waiting next release to break the ABI, it is smoother
to introduce the new code and enable it only for static libraries.
The flag RTE_NEXT_ABI may be used to "ifdef" the new code.
When the release is out, a dynamically linked application can use
the new shared libraries without rebuild while developpers can prepare
their application for the next ABI by reading the deprecation notice
and easily testing the new code.
When starting the next release cycle, the "ifdefs" will be removed
and the ABI break will be marked by incrementing LIBABIVER.
The new option CONFIG_RTE_NEXT_ABI is not defined in the configuration
templates because it is deduced from CONFIG_RTE_BUILD_SHARED_LIB.
It is automatically enabled for static libraries and disabled for
shared libraries.
It can be forced to another value by editing the generated .config file.
It shouldn't be enabled for shared libraries because it would break the
ABI without changing the version number LIBABIVER. That's why a warning
is printed in this case.
The guideline is also updated to integrate this new possibility.
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
---
doc/guides/guidelines/versioning.rst | 2 ++
lib/Makefile | 4 ++++
mk/rte.sdkconfig.mk | 3 +++
pkg/dpdk.spec | 1 +
scripts/validate-abi.sh | 2 ++
5 files changed, 12 insertions(+)
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
index a1c9368..6bc2a8e 100644
--- a/doc/guides/guidelines/versioning.rst
+++ b/doc/guides/guidelines/versioning.rst
@@ -57,6 +57,8 @@ being provided. The requirements for doing so are:
#. A full deprecation cycle, as explained above, must be made to offer
downstream consumers sufficient warning of the change.
+ The changes may be shown and used in static builds before the deprecation
+ cycle by conditioning them with RTE_NEXT_ABI option.
#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
incorporated must be incremented in parallel with the ABI changes
diff --git a/lib/Makefile b/lib/Makefile
index 5f480f9..ebf56ba 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -31,6 +31,10 @@
include $(RTE_SDK)/mk/rte.vars.mk
+ifeq '$(CONFIG_RTE_BUILD_SHARED_LIB)$(CONFIG_RTE_NEXT_ABI)' 'yy'
+$(info WARNING: Shared libraries versioning is tainted!)
+endif
+
DIRS-y += librte_compat
DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_MALLOC) += librte_malloc
diff --git a/mk/rte.sdkconfig.mk b/mk/rte.sdkconfig.mk
index f8d95b1..135825c 100644
--- a/mk/rte.sdkconfig.mk
+++ b/mk/rte.sdkconfig.mk
@@ -77,6 +77,9 @@ $(RTE_OUTPUT)/.config: $(RTE_CONFIG_TEMPLATE) FORCE | $(RTE_OUTPUT)
$(CPP) -undef -P -x assembler-with-cpp \
-ffreestanding \
-o $(RTE_OUTPUT)/.config_tmp $(RTE_CONFIG_TEMPLATE) ; \
+ printf 'CONFIG_RTE_NEXT_ABI=' >> $(RTE_OUTPUT)/.config_tmp ; \
+ sed -n 's,CONFIG_RTE_BUILD_SHARED_LIB=,,p' $(RTE_OUTPUT)/.config_tmp | \
+ tr 'yn' 'ny' >> $(RTE_OUTPUT)/.config_tmp ; \
if ! cmp -s $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config; then \
cp $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config ; \
cp $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config.orig ; \
diff --git a/pkg/dpdk.spec b/pkg/dpdk.spec
index 5f6ec6a..fb71ccc 100644
--- a/pkg/dpdk.spec
+++ b/pkg/dpdk.spec
@@ -82,6 +82,7 @@ make O=%{target} T=%{target} config
sed -ri 's,(RTE_MACHINE=).*,\1%{machine},' %{target}/.config
sed -ri 's,(RTE_APP_TEST=).*,\1n,' %{target}/.config
sed -ri 's,(RTE_BUILD_SHARED_LIB=).*,\1y,' %{target}/.config
+sed -ri 's,(RTE_NEXT_ABI=).*,\1n,' %{target}/.config
sed -ri 's,(LIBRTE_VHOST=).*,\1y,' %{target}/.config
sed -ri 's,(LIBRTE_PMD_PCAP=).*,\1y,' %{target}/.config
sed -ri 's,(LIBRTE_PMD_XENVIRT=).*,\1y,' %{target}/.config
diff --git a/scripts/validate-abi.sh b/scripts/validate-abi.sh
index 1747b8b..4476433 100755
--- a/scripts/validate-abi.sh
+++ b/scripts/validate-abi.sh
@@ -157,6 +157,7 @@ git checkout $TAG1
# Make sure we configure SHARED libraries
# Also turn off IGB and KNI as those require kernel headers to build
sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET
+sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET
sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET
sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET
@@ -198,6 +199,7 @@ git checkout $TAG2
# Make sure we configure SHARED libraries
# Also turn off IGB and KNI as those require kernel headers to build
sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET
+sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET
sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET
sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET
--
2.4.2
^ permalink raw reply [relevance 20%]
* Re: [dpdk-dev] [PATCH 2/3] doc: added guidelines on dpdk documentation
2015-07-02 13:50 3% ` [dpdk-dev] [PATCH 2/3] " John McNamara
@ 2015-07-02 16:20 0% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-07-02 16:20 UTC (permalink / raw)
To: John McNamara; +Cc: dev
2015-07-02 14:50, John McNamara:
> Added guidelines on the purpose and structure of the DPDK
> documentation, how to build it and guidelines for creating it.
>
> Also added guidelines on how to format and submit a documentation patch.
Good idea to have guidelines for doc.
But I think the submission guidelines shouldn't be specific to doc.
Could you move it to a contributing.rst file?
Guidelines from the website could be moved there.
> + In general developers do not have to update the Release Notes apart from
> + adding ABI announcements.
Someone must update the release notes.
Why not doing it atomicly when introducing a new feature?
> + The guideline documents record the DPDK guidelines on coding, design, ABI
> + usage and documentation.
> +
> + These should be changed to clarify or improve guidelines.
The guideline documents record community process, expectations and design
directions.
They can be extended, amended or discussed by submitting a patch and getting
community approval.
> +* Sphinx.
Sphinx (also called python-sphinx).
> +
> +* TexLive.
TexLive (at least TexLive-core, extra Latex support and extra fonts).
> + # Ubuntu/Debian.
> +
> + sudo apt-get -y install texlive-full
lighter:
sudo apt-get -y install texlive-latex-extra texlive-fonts-extra texlive-fonts-recommended
> + # Red Hat/Fedora, selective install.
> + sudo yum -y install texlive
> + sudo yum -y install texlive-latex
> + sudo yum -y install texlive-collection-latex
> + sudo yum -y install texlive-collection-latexrecommended
> + sudo yum -y install texlive-collection-latexextra
> + sudo yum -y install texlive-dejavu
simpler:
sudo yum -y install texlive-collection-latexextra, texlive-collection-fontsextra
> + aspell --lang=en_US --check doc/guides/sample_app_ug/mydoc.rst
Good tip!
What about making it more visible? :)
> +* Use one sentence per line in a paragraph, i.e., put a newline character
> + after each period/full stop.
What about adding this?
Only blank line will generate a newline.
I think breaking lines at end of sentence is more important than
wrapping at 80 char, because it will help to keep patches
readable.
> +* Use one line per paragraph.
Why this recommendation? I think it doesn't help.
> +* Avoid lines longer than 80 character in literal blocks since they can exceed
> + the page width when converted to PDF documentation. If possible try to wrap
> + the text at sensible locations. For example a long command line could be
> + documented like this and still work if copied directly from the docs::
> +
> + build/app/testpmd -c7 -n3 --vdev=eth_pcap0,iface=eth0 \
> + --vdev=eth_pcap1,iface=eth1 \
> + -- -i --nb-cores=2 --nb-ports=2 \
> + --total-num-mbufs=2048
Yes. Maybe that "avoid" is not strong enough.
> +* RST tables should be used sparingly. They are hard to format and to edit,
> + they are often rendered incorrectly in PDF format, and the same information
> + can usually be shown just as clearly with a list.
... or with a definition list.
> +* The use of a label is preferred since it works across files and will still
> + work if the header text changes.
Artificial labels are a bit ugly.
If a header change, there will be an error for the link, right?
> +Doxygen Guidelines
> +------------------
I think you should split your patch here and have a separate patch to move
the doxygen guidelines from the coding style doc.
> +Patching the Documentation
> +--------------------------
> +
> +One of the easiest ways to contribute to DPDK is to submit a patch to the
> +documentation.
> +
> +Over time the documentation may contain information that is slightly out of
> +date or that could be improved upon. Newcomers to the DPDK project often
> +notice these issues as they work through the examples and how-to guides.
> +
> +Rather than emailing the development list, or even ignoring the issue, it is
> +just as easy to submit a patch to fix it. The following instructions explain
> +how to do that and since they are meant to encourage contributions they assume
> +no development experience or prior exposure to the DPDK workflow.
> +
> +#. Install the documentation dependencies as shown above. As a minimum you
> + should install Sphinx::
> +
Using a link to above section would ease future update or extension.
> + # Ubuntu/Debian.
> + sudo apt-get -y install python-sphinx
> +
> + # Red Hat/Fedora.
> + sudo yum -y install python-sphinx
> +
> + If you are going to patch the API docs you will need Doxygen. You can omit
> + TexLive and Inkscape for now.
> +
>From this point, it could be a link to a starter section in a contributing doc.
> +#. Install ``git`` as follows::
[...]
> +#. Clone the DPDK repository (this can take a minute or two)::
[...]
>From this point, it is specific to doc.
> + make doc-guides-html
> +
> + If you get warnings about missing utilities go back and work through
> + installing the dependencies again.
[...]
> + You can ignore a warning about upgrading Sphinx, that is optional. If
> + you are building the documentation on Mac OS you can ignore a warning
> + from ``sed``.
Not aware of this warning. Could it be removed?
> +#. If everything is okay you can commit your changes to your local repository
> + and generate a patch. The first step is to add the file(s) that you
> + modified::
> +
> + git add doc/guides/linux_gsg/quick_start.rst
> +
> +#. Now commit the changes to the local repository. You must "sign" the commit
> + by using ``-s``. This will insert the name and email address that you
> + configured in your ``.gitconfig`` above::
> +
> + git commit -s
For a primer doc, "git commit -as" skip the "git add" step and would be OK.
> + doc: fix minor typo in linux getting started guide
> +
> + Fixed a minor typo in the Linux Getting Started Guide.
No need to repeat the title.
It would be more interesting to know why it is better after the patch.
In case of a typo, no comment is needed after the title.
>From this point, it is not specific to doc.
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH v3 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2
2015-07-02 15:16 4% ` [dpdk-dev] [PATCH v3 " John McNamara
@ 2015-07-02 15:16 14% ` John McNamara
2015-07-06 13:16 4% ` Thomas Monjalon
2015-07-03 8:22 0% ` [dpdk-dev] [PATCH v3 0/7] ethdev: add support for ieee1588 timestamping Lu, Wenzhuo
1 sibling, 1 reply; 200+ results
From: John McNamara @ 2015-07-02 15:16 UTC (permalink / raw)
To: dev
Add announcement of a dedicated additional field in the mbuf
to support ieee1588 in DPDK 2.2.
Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
doc/guides/rel_notes/abi.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..51dacb2 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,8 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+
+* In DPDK 2.1 the IEEE1588/802.1AS support in the i40e driver makes use of the
+ ``udata64`` field in the mbuf to pass the timesync register index to the
+ user. In DPDK 2.2 this will be moved to a new field in the mbuf.
+
--
1.8.1.4
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v3 0/7] ethdev: add support for ieee1588 timestamping
2015-06-29 13:42 4% [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping John McNamara
2015-06-29 13:42 14% ` [dpdk-dev] [PATCH v2 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
2015-07-02 1:24 0% ` [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping Lu, Wenzhuo
@ 2015-07-02 15:16 4% ` John McNamara
2015-07-02 15:16 14% ` [dpdk-dev] [PATCH v3 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
2015-07-03 8:22 0% ` [dpdk-dev] [PATCH v3 0/7] ethdev: add support for ieee1588 timestamping Lu, Wenzhuo
2 siblings, 2 replies; 200+ results
From: John McNamara @ 2015-07-02 15:16 UTC (permalink / raw)
To: dev
This patchset adds ethdev API to enable and read IEEE1588/802.1AS PTP timestamps from devices that support it. The following functions are added:
rte_eth_timesync_enable()
rte_eth_timesync_disable()
rte_eth_timesync_read_rx_timestamp()
rte_eth_timesync_read_tx_timestamp()
The "ieee1588" forwarding mode in testpmd is also refactored to demonstrate the new API and to clean up the code.
Adds support for igb, ixgbe and i40e.
V3:
* Fixed issued with version.map.
V2:
* Added i40e support.
* Renamed ethdev functions from rte_eth_ieee15888_*() to rte_eth_timesync_*()
since 802.1AS can be supported through the same interfaces.
V1:
* Initial version for
John McNamara (7):
ethdev: add support for ieee1588 timestamping
e1000: add support for ieee1588 timestamping
ixgbe: add support for ieee1588 timestamping
i40e: add support for ieee1588 timestamping
app/testpmd: refactor ieee1588 forwarding
doc: document ieee1588 forwarding mode
abi: announce mbuf addition for ieee1588 in DPDK 2.2
app/test-pmd/ieee1588fwd.c | 466 ++--------------------------
doc/guides/rel_notes/abi.rst | 5 +
doc/guides/testpmd_app_ug/run_app.rst | 2 +-
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 2 +
drivers/net/e1000/igb_ethdev.c | 115 +++++++
drivers/net/i40e/i40e_ethdev.c | 143 +++++++++
drivers/net/i40e/i40e_rxtx.c | 39 ++-
drivers/net/ixgbe/ixgbe_ethdev.c | 122 ++++++++
lib/librte_ether/rte_ethdev.c | 70 ++++-
lib/librte_ether/rte_ethdev.h | 90 +++++-
lib/librte_ether/rte_ether_version.map | 4 +
11 files changed, 615 insertions(+), 443 deletions(-)
--
1.8.1.4
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v2] doc: fix minor sphinx build warning
@ 2015-07-02 14:15 8% John McNamara
2015-07-06 14:55 0% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: John McNamara @ 2015-07-02 14:15 UTC (permalink / raw)
To: dev
Fix for a minor Sphinx build warning in the ABI guidelines docs:
versioning.rst:126: WARNING: Bullet list ends without a
blank line; unexpected unindent.
Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
doc/guides/guidelines/versioning.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
index a1c9368..ea789cb 100644
--- a/doc/guides/guidelines/versioning.rst
+++ b/doc/guides/guidelines/versioning.rst
@@ -122,9 +122,9 @@ The macros exported are:
the linker to bind references to symbol ``b`` to the internal symbol
``b_e``.
-* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the fully
-qualified function ``p``, so that if a symbol becomes versioned, it can still be
-mapped back to the public symbol name.
+* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the
+ fully qualified function ``p``, so that if a symbol becomes versioned, it
+ can still be mapped back to the public symbol name.
Examples of ABI Macro use
-------------------------
--
1.8.1.4
V2: Removed main heading label.
^ permalink raw reply [relevance 8%]
* [dpdk-dev] [PATCH 2/3] doc: added guidelines on dpdk documentation
@ 2015-07-02 13:50 3% ` John McNamara
2015-07-02 16:20 0% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: John McNamara @ 2015-07-02 13:50 UTC (permalink / raw)
To: dev
Added guidelines on the purpose and structure of the DPDK
documentation, how to build it and guidelines for creating it.
Also added guidelines on how to format and submit a documentation patch.
Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
doc/guides/guidelines/documentation.rst | 1005 +++++++++++++++++++++++++++++++
doc/guides/guidelines/index.rst | 2 +
2 files changed, 1007 insertions(+)
create mode 100644 doc/guides/guidelines/documentation.rst
diff --git a/doc/guides/guidelines/documentation.rst b/doc/guides/guidelines/documentation.rst
new file mode 100644
index 0000000..d3e5905
--- /dev/null
+++ b/doc/guides/guidelines/documentation.rst
@@ -0,0 +1,1005 @@
+g.. doc_guidelines:
+
+DPDK Documentation Guidelines
+=============================
+
+This document outlines the guidelines for writing the DPDK Guides and API
+documentation in RST and Doxygen format.
+
+It also explains the structure of the DPDK documentation and shows how to
+build the Html and PDF versions of the documents.
+
+It also explains how to submit a patch to the documentation.
+
+
+Structure of the Documentation
+------------------------------
+
+The DPDK source code repository contains input files to build the API
+documentation and User Guides.
+
+The main directories that contain files related to documentation are shown
+below::
+
+ lib
+ |-- librte_acl
+ |-- librte_cfgfile
+ |-- librte_cmdline
+ |-- librte_compat
+ |-- librte_eal
+ | |-- ...
+ ...
+ doc
+ |-- api
+ +-- guides
+ |-- freebsd_gsg
+ |-- linux_gsg
+ |-- prog_guide
+ |-- sample_app_ug
+ |-- guidelines
+ |-- testpmd_app_ug
+ |-- rel_notes
+ |-- nics
+ |-- xen
+ |-- ...
+
+
+The API documentation is built from `Doxygen
+<http://www.stack.nl/~dimitri/doxygen/>`_ comments in the header files. These
+files are mainly in the ``lib/lib_rte_*`` directories although some of the
+Poll Mode Drivers in ``drivers/net`` are also documented with Doxygen.
+
+The configuration files that are used to control the Doxygen output are in the
+``doc/api`` directory.
+
+The user guides such as *The Programmers Guide* and the *FreeBSD* and *Linux
+Getting Started* Guides are generated from RST markup text files using the
+`Sphinx <http://sphinx-doc.org/index.html>`_ Documentation Generator.
+
+These files are included in the ``doc/guides/`` directory. The output is
+controlled by the ``doc/guides/conf.py`` file.
+
+
+Role of the Documentation
+-------------------------
+
+The following items outline the roles of the different parts of the
+documentation and when they need to be updated or added to by the developer.
+
+* **Release Notes**
+
+ The Release Notes document which features have been added in the current and
+ previous releases of DPDK and highlight any known issues. The Releases Notes
+ also contain notifications of features that will change ABI compatibility in
+ the next major release.
+
+ In general developers do not have to update the Release Notes apart from
+ adding ABI announcements.
+
+* **API documentation**
+
+ The API documentation explains how to use the public DPDK functions. The
+ `API index page <http://dpdk.org/doc/api/>`_ shows the generated API
+ documentation as related groups of functions.
+
+ The API documentation should be updated via Doxygen comments when new
+ functions are added.
+
+* **Getting Started Guides**
+
+ The Getting Started Guides show how to install and configure DPDK and
+ how to run DPDK based applications on different OSes.
+
+ A Getting Started Guide should be added when DPDK is ported to a new OS. The
+ guide for the Skeleton Forwarding app is a good starting reference.
+
+* **The Programmers Guide**
+
+ The Programmers Guide explains how the API components of DPDK such as
+ the EAL, Memzone, Rings and the Hash Library work. It also explains how some
+ higher level functionality such as Packet Distributor, Packet Framework and
+ KNI work. It also shows the build system and explains how to add
+ applications.
+
+ The Programmers Guide should be expanded when new functionality is added to
+ DPDK.
+
+* **App Guides**
+
+ The app guides document the DPDK applications in the ``app`` directory such
+ as ``testpmd``.
+
+ The app guides should be updated if functionality is changed or added.
+
+* **Sample App Guides**
+
+ The sample app guides document the DPDK example applications in the examples
+ directory. Generally they demonstrate a major feature such as L2 or L3
+ Forwarding, Multi Process or Power Management. They explain the purpose of
+ the sample application, how to run it and step through some of the code to
+ explain the major functionality.
+
+ A new sample application should be accompanied by new sample app guide.
+
+* **Network Interface Controller Drivers**
+
+ The NIC Drivers document explains the features of the individual Poll Mode
+ Drivers, such as software requirements, configuration and initialization.
+
+ New documentation should be added for new Poll Mode Drivers.
+
+* **Guidelines**
+
+ The guideline documents record the DPDK guidelines on coding, design, ABI
+ usage and documentation.
+
+ These should be changed to clarify or improve guidelines.
+
+
+Building the Documentation
+--------------------------
+
+Dependencies
+~~~~~~~~~~~~
+
+
+The following dependencies must be installed to build the documentation:
+
+* Doxygen.
+
+* Sphinx.
+
+* TexLive.
+
+* Inkscape.
+
+`Doxygen`_ generates documentation from commented source code. It can be
+installed as follows:
+
+.. code-block:: console
+
+ # Ubuntu/Debian.
+ sudo apt-get -y install doxygen
+
+ # Red Hat/Fedora.
+ sudo yum -y install doxygen
+
+`Sphinx`_ is a Python documentation tool for converting RST files to Html or
+to PDF (via LaTeX). It can be installed as follows:
+
+.. code-block:: console
+
+ # Ubuntu/Debian.
+ sudo apt-get -y install python-sphinx
+
+ # Red Hat/Fedora.
+ sudo yum -y install python-sphinx
+
+ # Or, on any system with Python installed.
+ sudo easy_install -U sphinx
+
+For further information on getting started with Sphinx see the `Sphinx
+Tutorial <http://sphinx-doc.org/tutorial.html>`_.
+
+.. Note::
+
+ To get full support for Figure and Table numbering it is best to install
+ Sphinx 1.3.1 or later.
+
+
+`Inkscape`_ is a vector based graphics program which is used to create SVG
+images and also to convert SVG images to PDF images. It can be installed as
+follows:
+
+.. code-block:: console
+
+ # Ubuntu/Debian.
+ sudo apt-get -y install inkscape
+
+ # Red Hat/Fedora.
+ sudo yum -y install inkscape
+
+`TexLive <http://www.tug.org/texlive/>`_ is an installation package for
+Tex/LaTeX. It is used to generate the PDF versions of the
+documentation. Installation of all of the TeX components required by Sphinx
+can be tricky. If possible it is best to install TexLive Full to ensure that
+you have all the requirements. It can be installed as follows:
+
+.. code-block:: console
+
+ # Ubuntu/Debian.
+
+ sudo apt-get -y install texlive-full
+
+ # Red Hat/Fedora, selective install.
+ sudo yum -y install texlive
+ sudo yum -y install texlive-latex
+ sudo yum -y install texlive-collection-latex
+ sudo yum -y install texlive-collection-latexrecommended
+ sudo yum -y install texlive-collection-latexextra
+ sudo yum -y install texlive-dejavu
+
+
+Build commands
+~~~~~~~~~~~~~~
+
+The documentation is built using the standard DPDK build system. Some examples
+are shown below:
+
+* Generate all the documentation targets::
+
+ make doc
+
+* Generate the Doxygen API documentation in Html::
+
+ make doc-api-html
+
+* Generate the guides documentation in Html::
+
+ make doc-guides-html
+
+* Generate the guides documentation in Pdf::
+
+ make doc-guides-pdf
+
+The output of these commands is generated in the ``build`` directory::
+
+ build/doc
+ |-- html
+ | |-- api
+ | +-- guides
+ |
+ +-- pdf
+ +-- guides
+
+
+.. Note::
+
+ Make sure to fix any Sphinx or Doxygen warnings when adding or updating
+ documentation.
+
+The documentation output files can be removed as follows::
+
+ make doc-clean
+
+
+Document Guidelines
+-------------------
+
+Here are some guidelines in relation to the style of the documentation:
+
+* Document the obvious as well as the obscure since it won't always be obvious
+ to the reader. For example an instruction like "Set up 64 2MB Hugepages" is
+ better when followed by a sample commandline or a link to the appropriate
+ section of the documentation.
+
+* Use American English spellings throughout. This can be checked using the
+ ``aspell`` utility::
+
+ aspell --lang=en_US --check doc/guides/sample_app_ug/mydoc.rst
+
+
+RST Guidelines
+--------------
+
+The RST (reStructuredText) format is a plain text markup format that can be
+converted to Html, PDF or other formats. It is most closely associated with
+Python but it can be used to document any language. It is used in DPDK to
+document everything apart from the API.
+
+The Sphinx documentation contains a very useful `RST Primer
+<http://sphinx-doc.org/rest.html#rst-primer>`_ which is a good place to learn
+the minimal set of syntax required to format a document.
+
+The official `reStructuredText <http://docutils.sourceforge.net/rst.html>`_
+website contains the specification for the RST format and also examples of how
+to use it. However, for most developers the RST Primer above is a better
+resource.
+
+The most common guidelines for writing RST text are detailed in the
+`Documenting Python <https://docs.python.org/devguide/documenting.html>`_
+guidelines. The additional guidelines below reiterate or expand upon those
+guidelines.
+
+
+Readability
+~~~~~~~~~~~
+
+The main RST guideline is that the RST text should be readable in text format.
+
+Even though RST is a markup format and the text will most often be read when
+rendered to Html or PDF it is important to maintain readability of the raw
+text. This makes is easier for developers to read in an editor or in a
+terminal.
+
+
+Line Length
+~~~~~~~~~~~
+
+The existing documentation contains different styles for long lines and
+paragraphs. The following are recommendations for new text in order of
+preference:
+
+* Wrap lines at 80 characters. This is the Python RST recommendation and adds
+ to readability of the raw text.
+
+* Use one sentence per line in a paragraph, i.e., put a newline character
+ after each period/full stop.
+
+* Use one line per paragraph.
+
+
+Whitespace
+~~~~~~~~~~
+
+* Standard RST indentation is 3 spaces. Code can be indented 4 spaces,
+ especially if it is copied from source files.
+
+* No tabs. Convert tabs in embedded code to 4 or 8 spaces.
+
+* No trailing whitespace.
+
+* The most common existing style in the documentation is to have only 1 space
+ after a period/full stop.
+
+* Add 2 blank lines before each section header.
+
+* Add 1 blank line after each section header.
+
+* Add 1 blank line between each line of a list.
+
+
+Section Headers
+~~~~~~~~~~~~~~~
+
+* Section headers should use the use the following underline formats::
+
+ Level 1 Heading
+ ===============
+
+
+ Level 2 Heading
+ ---------------
+
+
+ Level 3 Heading
+ ~~~~~~~~~~~~~~~
+
+
+ Level 4 Heading
+ ^^^^^^^^^^^^^^^
+
+
+* Level 4 headings should be used sparingly.
+
+* The underlines should match the length of the text.
+
+* In general, the heading should be less than 80 characters.
+
+* As noted above:
+
+ * Add 2 blank lines before each section header.
+
+ * Add 1 blank line after each section header.
+
+
+Lists
+~~~~~
+
+* Bullet lists should be formatted with a leading ``*`` as follows::
+
+ * Item one.
+
+ * Item two is a longer line that is wrapped at 80 characters and then
+ indented to match the start of the first line.
+
+ * One space character between the bullet and the text is preferred.
+
+* Numbered lists can be formatted with a leading number but the preference is
+ to use ``#.`` which will give automatic numbering. This is more convenient
+ when adding or removing items::
+
+ #. Item one.
+
+ #. Item two is a longer line that is wrapped at 80 characters and then
+ indented to match the start of the e first line.
+
+* Definition lists can be written with or without a bullet::
+
+ * Item one.
+
+ Some text about item one.
+
+ * Item two.
+
+ Some text about item two.
+
+* All lists, and sub-lists, must be separated from the preceding text by a
+ blank line. This is a syntax requirement.
+
+* All list items should be separated by a blank line for readability.
+
+
+Code and Literal block sections
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Inline text that is required to be rendered with a fixed width font should
+ be enclosed in backquotes like this: \`\`text\`\`, so that it appears like
+ this: ``text``.
+
+* Fixed width, literal blocks of texts should be indented at least 3 spaces
+ and prefixed with ``::`` like this::
+
+ Here is some fixed width text::
+
+ 0x0001 0x0001 0x00FF 0x00FF
+
+* It is also possible to specify an encoding for a literal block using the
+ ``.. code-block::`` directive so that syntax highlighting can be
+ applied. Examples of supported highlighting are::
+
+ .. code-block:: console
+ .. code-block:: c
+ .. code-block:: python
+ .. code-block:: diff
+ .. code-block:: none
+
+ That can be applied as follows::
+
+ .. code-block:: c
+
+ #include<stdio.h>
+
+ int main() {
+
+ printf("Hello World\n");
+
+ return 0;
+ }
+
+ Which would be rendered as:
+
+ .. code-block:: c
+
+ #include<stdio.h>
+
+ int main() {
+
+ printf("Hello World\n");
+
+ return 0;
+ }
+
+
+* The default encoding for a literal block using the simplified ``::``
+ directive is ``none``.
+
+* Avoid lines longer than 80 character in literal blocks since they can exceed
+ the page width when converted to PDF documentation. If possible try to wrap
+ the text at sensible locations. For example a long command line could be
+ documented like this and still work if copied directly from the docs::
+
+ build/app/testpmd -c7 -n3 --vdev=eth_pcap0,iface=eth0 \
+ --vdev=eth_pcap1,iface=eth1 \
+ -- -i --nb-cores=2 --nb-ports=2 \
+ --total-num-mbufs=2048
+
+
+Images
+~~~~~~
+
+* All images should be in SVG scalar graphics format. They should be true SVG
+ XML files and should not include binary formats embedded in a SVG wrapper.
+
+* The DPDK documentation contains some legacy images in PNG format. These will
+ be converted to SVG in time.
+
+* `Inkscape <inkscape.org>`_ is the recommended graphics editor for creating
+ the images. Use some of the older images in ``doc/guides/prog_guide/img/``
+ as a template, for example ``mbuf1.svg`` or ``ring-enqueue.svg``.
+
+* The SVG images should include a copyright notice, as an XML comment.
+
+* Images in the documentation should be formatted as follows:
+
+ * The image should be preceded by a label in the format
+ ``.. _figure_XXXX:`` with a leading underscore and where ``XXXX`` is a
+ unique descriptive name.
+
+ * Images should be included using the ``.. figure::`` directive and the
+ file type should be set to ``*`` (not ``.svg``). This allows the format
+ of the image to be changed if required.
+
+ * Images must have a caption as part of the ``.. figure::`` directive.
+
+* Here is an example of the previous three guidelines::
+
+ .. _figure_mempool:
+
+ .. figure:: img/mempool.*
+
+ A mempool in memory with its associated ring.
+
+.. _mock_label:
+
+* Images can then be linked to using the ``:numref:`` directive::
+
+ The mempool layout is shown in :numref:`figure_mempool`.
+
+ This would be rendered as: *The mempool layout is shown in* :ref:`Fig 6.3
+ <mock_label>`.
+
+ **Note**: The ``:numref:`` directive requires Sphinx 1.3.1 or later. With
+ earlier versions it will still be rendered as a link but won't have an
+ automatically generated number.
+
+* The caption of the image can be generated, with a link, using the ``:ref:``
+ directive::
+
+ :ref:`figure_mempool`
+
+ This would be rendered as: *A mempool in memory with its associated ring.*
+
+Tables
+~~~~~~
+
+* RST tables should be used sparingly. They are hard to format and to edit,
+ they are often rendered incorrectly in PDF format, and the same information
+ can usually be shown just as clearly with a list.
+
+* Tables in the documentation should be formatted as follows:
+
+ * The table should be preceded by a label in the format
+ ``.. _table_XXXX:`` with a leading underscore and where ``XXXX`` is a
+ unique descriptive name.
+
+ * Tables should be included using the ``.. table::`` directive and must
+ have a caption.
+
+* Here is an example of the previous two guidelines::
+
+ .. _table_qos_pipes:
+
+ .. table:: Sample configuration for QOS pipes.
+
+ +----------+----------+----------+
+ | Header 1 | Header 2 | Header 3 |
+ | | | |
+ +==========+==========+==========+
+ | Text | Text | Text |
+ +----------+----------+----------+
+ | ... | ... | ... |
+ +----------+----------+----------+
+
+* Tables can be linked to using the ``:numref:`` and ``:ref:`` directives, as
+ shown in the previous section for images. For example::
+
+ The QOS configuration is shown in :numref:`table_qos_pipes`.
+
+* Tables should not include merged cells since they are not supported by the
+ PDF renderer.
+
+
+.. _links:
+
+Hyperlinks
+~~~~~~~~~~
+
+* Links to external websites can be plain URLs. The following is rendered as
+ http://dpdk.org::
+
+ http://dpdk.org
+
+* They can contain alternative text. The following is rendered as
+ `Check out DPDK <http://dpdk.org>`_::
+
+ `Check out DPDK <http://dpdk.org>`_
+
+* An internal link can be generated by placing labels in the document with the
+ format ``.. _label_name``.
+
+* The following links to the top of this section: :ref:`links`::
+
+ .. _links:
+
+ Hyperlinks
+ ~~~~~~~~~~
+
+ * The following links to the top of this section: :ref:`links`:
+
+.. Note::
+
+ The label must have a leading underscore but the reference to it must omit
+ it. This is a frequent cause of errors and warnings.
+
+* The use of a label is preferred since it works across files and will still
+ work if the header text changes.
+
+
+.. _doxygen_guidelines:
+
+Doxygen Guidelines
+------------------
+
+The DPDK API is documented using Doxygen comment annotations in the header
+files. Doxygen is a very powerful tool, it is extremely configurable and with
+a little effort can be used to create expressive documents. See the `Doxygen
+website <http://www.stack.nl/~dimitri/doxygen/>`_ for full details on how to
+use it.
+
+The following are some guidelines for use of Doxygen in the DPDK API
+documentation:
+
+* New libraries that are documented with Doxygen should be added to the
+ Doxygen configuration file: ``doc/api/doxy-api.conf``. It is only required
+ to add the directory that contains the files. It isn't necessary to
+ explicitly name each file since the configuration matches all ``rte_*.h``
+ files in the directory.
+
+* Use proper capitalization and punctuation in the Doxygen comments since they
+ will become sentences in the documentation. This in particular applies to
+ single line comments, which is the case the is most often forgotten.
+
+* Use ``@`` style Doxygen commands instead of ``\`` style commands.
+
+* Add a general description of each library at the head of the main header
+ files:
+
+ .. code-block:: c
+
+ /**
+ * @file
+ * RTE Mempool.
+ *
+ * A memory pool is an allocator of fixed-size object. It is
+ * identified by its name, and uses a ring to store free objects.
+ * ...
+ */
+
+* Document the purpose of a function, the parameters used and the return
+ value:
+
+ .. code-block:: c
+
+ /**
+ * Attach a new Ethernet device specified by arguments.
+ *
+ * @param devargs
+ * A pointer to a strings array describing the new device
+ * to be attached. The strings should be a pci address like
+ * `0000:01:00.0` or **virtual** device name like `eth_pcap0`.
+ * @param port_id
+ * A pointer to a port identifier actually attached.
+ *
+ * @return
+ * 0 on success and port_id is filled, negative on error.
+ */
+ int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+
+* Doxygen supports Markdown style syntax such as bold, italics, fixed width
+ text and lists. For example the second line in the ``devargs`` parameter in
+ the previous example will be rendered as:
+
+ The strings should be a pci address like ``0000:01:00.0`` or **virtual**
+ device name like ``eth_pcap0``.
+
+* Use ``-`` instead of ``*`` for lists within the Doxygen comment since the
+ latter can get confused with the comment delimiter.
+
+* Add an empty line between the function description, the ``@params`` and
+ ``@return`` for readability.
+
+* Place the ``@params`` description on separate line and indent it by 2
+ spaces. (It would be better to use no indentation since this is more common
+ and also because checkpatch complains about leading whitespace in
+ comments. However this is the convention used in the existing DPDK code.)
+
+* Documented functions can be linked to simply by adding ``()`` to the
+ function name:
+
+ .. code-block:: c
+
+ /**
+ * The functions exported by the application Ethernet API to setup
+ * a device designated by its port identifier must be invoked in
+ * the following order:
+ * - rte_eth_dev_configure()
+ * - rte_eth_tx_queue_setup()
+ * - rte_eth_rx_queue_setup()
+ * - rte_eth_dev_start()
+ */
+
+ In the API documentation the functions will be rendered as links, see the
+ `online section of the rte_ethdev.h docs
+ <http://dpdk.org/doc/api/rte__ethdev_8h.html>`_ that contains the above
+ text.
+
+* The ``@see`` keyword can be used to create a *see also* link to another file
+ or library. This directive should be placed on one line at the bottom of the
+ documentation section.
+
+ .. code-block:: c
+
+ /**
+ * ...
+ *
+ * Some text that references mempools.
+ *
+ * @see eal_memzone.c
+ */
+
+* Doxygen supports two types of comments for documenting variables, constants
+ and members: prefix and postfix:
+
+ .. code-block:: c
+
+ /** This is a prefix comment. */
+ #define RTE_FOO_ERROR 0x023.
+
+ #define RTE_BAR_ERROR 0x024. /**< This is a postfix comment. */
+
+* Postfix comments are preferred for struct members and constants if they can
+ be documented in the same way:
+
+ .. code-block:: c
+
+ struct rte_eth_stats {
+ uint64_t ipackets; /**< Total number of received packets. */
+ uint64_t opackets; /**< Total number of transmitted packets.*/
+ uint64_t ibytes; /**< Total number of received bytes. */
+ uint64_t obytes; /**< Total number of transmitted bytes. */
+ uint64_t imissed; /**< Total of RX missed packets. */
+ uint64_t ibadcrc; /**< Total of RX packets with CRC error. */
+ uint64_t ibadlen; /**< Total of RX packets with bad length. */
+ }
+
+ Note: postfix comments should be aligned with spaces not tabs in accordance
+ with the :ref:`coding_style`.
+
+* If a single comment type can't be used, due to line length limitations then
+ prefix comments should be preferred. For example this section of the code
+ contains prefix comments, postfix comments on the same line and postfix
+ comments on a separate line:
+
+ .. code-block:: c
+
+ /** Number of elements in the elt_pa array. */
+ uint32_t pg_num __rte_cache_aligned;
+ uint32_t pg_shift; /**< LOG2 of the physical pages. */
+ uintptr_t pg_mask; /**< Physical page mask value. */
+ uintptr_t elt_va_start;
+ /**< Virtual address of the first mempool object. */
+ uintptr_t elt_va_end;
+ /**< Virtual address of the <size + 1> mempool object. */
+ phys_addr_t elt_pa[MEMPOOL_PG_NUM_DEFAULT];
+ /**< Array of physical page addresses for the mempool buffer. */
+
+ This doesn't have an effect on the rendered documentation but it is
+ confusing for the developer reading the code. It this case it would be
+ clearer to use prefix comments throughout:
+
+ .. code-block:: c
+
+ /** Number of elements in the elt_pa array. */
+ uint32_t pg_num __rte_cache_aligned;
+ /** LOG2 of the physical pages. */
+ uint32_t pg_shift;
+ /** Physical page mask value. */
+ uintptr_t pg_mask;
+ /** Virtual address of the first mempool object. */
+ uintptr_t elt_va_start;
+ /** Virtual address of the <size + 1> mempool object. */
+ uintptr_t elt_va_end;
+ /** Array of physical page addresses for the mempool buffer. */
+ phys_addr_t elt_pa[MEMPOOL_PG_NUM_DEFAULT];
+
+* Check for Doxygen warnings in new code by checking the API documentation
+ build::
+
+ make doc-api-html | grep "warning:"
+
+* Read the rendered section of the documentation that you have added for
+ correctness, clarity and consistency with the surrounding text.
+
+
+Patching the Documentation
+--------------------------
+
+One of the easiest ways to contribute to DPDK is to submit a patch to the
+documentation.
+
+Over time the documentation may contain information that is slightly out of
+date or that could be improved upon. Newcomers to the DPDK project often
+notice these issues as they work through the examples and how-to guides.
+
+Rather than emailing the development list, or even ignoring the issue, it is
+just as easy to submit a patch to fix it. The following instructions explain
+how to do that and since they are meant to encourage contributions they assume
+no development experience or prior exposure to the DPDK workflow.
+
+#. Install the documentation dependencies as shown above. As a minimum you
+ should install Sphinx::
+
+ # Ubuntu/Debian.
+ sudo apt-get -y install python-sphinx
+
+ # Red Hat/Fedora.
+ sudo yum -y install python-sphinx
+
+ If you are going to patch the API docs you will need Doxygen. You can omit
+ TexLive and Inkscape for now.
+
+#. Install ``git`` as follows::
+
+ # Ubuntu/Debian.
+ sudo apt-get -y install git
+
+ # Red Hat/Fedora.
+ sudo yum -y install git
+
+ If you have any problems, refer to the official `Git installation guide
+ <https://git-scm.com/book/en/v2/Getting-Started-Installing-Git>`_.
+
+#. Configure your ``.gitconfig`` file with your name and email address::
+
+ git config --global user.name "J. Smith"
+ git config --global user.email jsmith@example.com
+
+ If you wish you can also configure the default editor that is used to write
+ commit messages::
+
+ git config --global core.editor vi
+
+ See the `Git getting started guide
+ <https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup>`_ if
+ you have any issues.
+
+#. Clone the DPDK repository (this can take a minute or two)::
+
+ git clone http://dpdk.org/git/dpdk
+
+#. Change into the new ``dpdk`` directory and test if you have the required
+ dependencies to build the docs::
+
+ cd dpdk
+ make doc-guides-html
+
+ If you get warnings about missing utilities go back and work through
+ installing the dependencies again.
+
+ If you installed some of the other dependencies you can try the following,
+ but they aren't required::
+
+ # If you installed Doxygen:
+ make doc-api-html
+
+ # If you installed Inkscape and TexLive as well:
+ make doc
+
+ .. Note::
+
+ You can ignore a warning about upgrading Sphinx, that is optional. If
+ you are building the documentation on Mac OS you can ignore a warning
+ from ``sed``.
+
+#. Using your preferred editor make the changes to the file you want to fix or
+ improve. For example::
+
+ vi doc/guides/linux_gsg/quick_start.rst
+
+#. Once you have make the modifications you should see a change in the ``git
+ status``::
+
+ git status
+
+ On branch master
+ Your branch is up-to-date with 'origin/master'.
+ Changes not staged for commit:
+ (use "git add <file>..." to update what will be committed)
+ (use "git checkout -- <file>..." to discard changes)
+
+ modified: doc/guides/linux_gsg/quick_start.rst
+
+
+#. You will be able to review your changes using ``git diff``:
+
+ .. code-block:: diff
+
+ git diff
+
+ diff --git a/quick_start.rst b/quick_start.rst
+ index b07fc87..7b49e1c 100644
+ --- a/doc/guides/linux_gsg/quick_start.rst
+ +++ b/doc/guides/linux_gsg/quick_start.rst
+ @@ -256,7 +256,7 @@ The following selection demonstrates the launch
+
+ Enter hex bitmask of cores to execute test app on
+ Example: to execute app on cores 0 to 7, enter 0xff
+ - bitmaks: 0x01
+ + bitmask: 0x01
+ Launching app
+ EAL: coremask set to 1
+ EAL: Detected lcore 0 on socket 0
+
+ Two other diff options that are useful when dealing with changes to
+ documentation are word and character diffs::
+
+ # View differences by word instead of lines:
+ git diff --color-words
+
+ # View differences by character:
+ git diff --color-words=.
+
+
+#. Rebuild the docs and fix any new warnings::
+
+ make doc-guides-html
+
+#. Open the output Html document and review your changes in the context of the
+ surrounding text. Use a Web browser like the following::
+
+ firefox build/doc/html/guides/linux_gsg/quick_start.html &
+
+#. If everything is okay you can commit your changes to your local repository
+ and generate a patch. The first step is to add the file(s) that you
+ modified::
+
+ git add doc/guides/linux_gsg/quick_start.rst
+
+#. Now commit the changes to the local repository. You must "sign" the commit
+ by using ``-s``. This will insert the name and email address that you
+ configured in your ``.gitconfig`` above::
+
+ git commit -s
+
+ This will drop you into the default, or configured, editor and you can
+ insert a message like the following::
+
+ doc: fix minor typo in linux getting started guide
+
+ Fixed a minor typo in the Linux Getting Started Guide.
+
+ Signed-off-by: J. Smith <jsmith@example.com>
+
+ The first line will be used as a subject line for an email so it should:
+
+ * start with ``doc:``
+ * be less than 50 characters
+ * be lowercase only
+ * and not end with a period/full stop
+
+ The body of the text should:
+
+ * describe the change
+ * be wrapped at 72 characters
+ * have proper punctuation and capitalization
+
+ The body of the message should generally be longer than the example above
+ and should explain the purpose of the change.
+
+#. You can now create and email a patch. This can be done in one step from git
+ but for beginners it is best done in two steps so that you can review the
+ patch. First generate the patch::
+
+ git format-patch -1
+
+ This will generate a patch like the following::
+
+ 0001-doc-fix-minor-typo-in-linux-getting-started-guide.patch
+
+ If you have a large patch or set of patches you can also generate a cover
+ letter to explain the changes by adding the ``--cover-letter`` option.
+
+
+#. If you are happy that everything looks good you can sent the patch to the
+ DPDK ``dev`` mailing list::
+
+ git send-mail --to dev@dpdk.org 0001-doc-fix-minor-typo-etc.patch
+
+ If you have issues see the `git send-mail
+ <http://git-scm.com/docs/git-send-email>`_ section of the the Git
+ documentation.
+
+ If all goes well the patch will appear on the `DPDK dev mailing list
+ <http://dpdk.org/ml/listinfo/dev>`_ and in the `DPDK Patchwork
+ <http://dpdk.org/dev/patchwork/project/dpdk/list/>`_.
diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
index bfb9fa3..1050d99 100644
--- a/doc/guides/guidelines/index.rst
+++ b/doc/guides/guidelines/index.rst
@@ -8,3 +8,5 @@ Guidelines
coding_style
design
versioning
+ documentation
+
--
1.8.1.4
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH] doc: fix minor sphinx build warning
2015-07-02 12:18 3% ` Thomas Monjalon
@ 2015-07-02 13:28 0% ` Mcnamara, John
0 siblings, 0 replies; 200+ results
From: Mcnamara, John @ 2015-07-02 13:28 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Thursday, July 2, 2015 1:18 PM
> To: Mcnamara, John
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH] doc: fix minor sphinx build warning
>
> But it could be useful in case new versioning chapters are added before
> ABI guidelines.
> In this case, the link referenced in the commit above should be updated.
Hi Thomas,
I'll just resubmit without the label part of the patch and submit a patch for the label at a later stage, if required.
John
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v4 3/4] bond mode 4: allow external state machine
@ 2015-07-02 13:30 4% ` Declan Doherty
0 siblings, 0 replies; 200+ results
From: Declan Doherty @ 2015-07-02 13:30 UTC (permalink / raw)
To: Eric Kinzie, dev; +Cc: Eric Kinzie
On 26/05/15 16:41, Eric Kinzie wrote:
> From: Eric Kinzie <ekinzie@brocade.com>
>
> Provide functions to allow an external 802.3ad state machine to transmit
> and recieve LACPDUs and to set the collection/distribution flags on
> slave interfaces.
>
> Size of struct rte_eth_bond_8023ad_conf changed. Increment LIBABIVER
> and version bond_mode_8023ad_setup and bond_mode_8023ad_conf_get
> functions.
>
> Signed-off-by: Eric Kinzie <ehkinzie@gmail.com>
> ---
....
>
Hey Eric, sorry for talking so long to get back with these comments.
I had some issues with the ABI versioning and the static linking with
the test app, also the ABI versioning wasn't implemented as specified in
the latest guidelines document, I had to make the following changes to
get things to link correctly for me. Also in
rte_eth_bond_8023ad_ext_slowtx it's probably worth while checking the
ethertype in the eth header.
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.c
b/drivers/net/bonding/rte_eth_bond_8023ad.c
index 06534ae..a9e6a50 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad.c
+++ b/drivers/net/bonding/rte_eth_bond_8023ad.c
@@ -1001,7 +1001,7 @@ bond_mode_8023ad_mac_address_update(struct
rte_eth_dev *bond_dev)
bond_mode_8023ad_start(bond_dev);
}
-void __vsym
+void
bond_mode_8023ad_conf_get_v20(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf)
{
@@ -1020,9 +1020,8 @@ bond_mode_8023ad_conf_get_v20(struct rte_eth_dev *dev,
conf->slowrx_cb = mode4->slowrx_cb;
}
-VERSION_SYMBOL(bond_mode_8023ad_conf_get, _v20, 2.0);
-void __vsym
+void
bond_mode_8023ad_conf_get_v21(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf)
{
@@ -1041,9 +1040,10 @@ bond_mode_8023ad_conf_get_v21(struct rte_eth_dev
*dev,
conf->slowrx_cb = mode4->slowrx_cb;
}
-BIND_DEFAULT_SYMBOL(bond_mode_8023ad_conf_get, _v21, 2.1);
+MAP_STATIC_SYMBOL(void bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_bond_8023ad_conf *conf), bond_mode_8023ad_conf_get_v21);
-void __vsym
+void
bond_mode_8023ad_setup_v20(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf)
{
@@ -1074,9 +1074,8 @@ bond_mode_8023ad_setup_v20(struct rte_eth_dev *dev,
mode4->update_timeout_us = conf->update_timeout_ms * 1000;
}
-VERSION_SYMBOL(bond_mode_8023ad_setup, _v20, 2.0);
-void __vsym
+void
bond_mode_8023ad_setup_v21(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf)
{
@@ -1114,8 +1113,9 @@ bond_mode_8023ad_setup_v21(struct rte_eth_dev *dev,
bond_mode_8023ad_start(dev);
}
-BIND_DEFAULT_SYMBOL(bond_mode_8023ad_setup, _v21, 2.1);
-
+MAP_STATIC_SYMBOL(void bond_mode_8023ad_setup(struct rte_eth_dev *dev,
+ struct rte_eth_bond_8023ad_conf *conf),
+ bond_mode_8023ad_setup_v21);
int
bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)
{
@@ -1407,7 +1407,8 @@ rte_eth_bond_8023ad_ext_slowtx(uint8_t port_id,
uint8_t slave_id,
/* only enqueue LACPDUs */
lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
- if (lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
+ if (lacp-> eth_hdr. ether_type != rte_cpu_to_be(ETHER_TYPE_SLOW) ||
+ lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
return -EINVAL;
MODE4_DEBUG("sending LACP frame\n");
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad_private.h
b/drivers/net/bonding/rte_eth_bond_8023ad_private.h
index cb39004..d1a1af0 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad_private.h
+++ b/drivers/net/bonding/rte_eth_bond_8023ad_private.h
@@ -191,7 +191,7 @@ struct bond_dev_private;
/**
* @internal
*
- * Get configuration of bonded interface.
+ * Retreive mode 4 configuration of bonded interface.
*
*
* @param dev Bonded interface
@@ -201,6 +201,18 @@ void
bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf);
+void
+bond_mode_8023ad_conf_get_v20(struct rte_eth_dev *dev,
+ struct rte_eth_bond_8023ad_conf *conf);
+
+VERSION_SYMBOL(bond_mode_8023ad_conf_get, _v20, 2.0);
+
+void
+bond_mode_8023ad_conf_get_v21(struct rte_eth_dev *dev,
+ struct rte_eth_bond_8023ad_conf *conf);
+
+BIND_DEFAULT_SYMBOL(bond_mode_8023ad_conf_get, _v21, 2.1);
+
/**
* @internal
*
@@ -214,31 +226,19 @@ bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
void
bond_mode_8023ad_setup(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf);
-void __vsym
+void
bond_mode_8023ad_setup_v20(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf);
-void __vsym
-bond_mode_8023ad_setup_v21(struct rte_eth_dev *dev,
- struct rte_eth_bond_8023ad_conf *conf);
-/**
- * @internal
- *
- * Retreive mode 4 configuration of bonded interface.
- *
- * @param dev Bonded interface
- * @param conf Bonded interface configuration
- */
+VERSION_SYMBOL(bond_mode_8023ad_setup, _v20, 2.0);
+
void
-bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
- struct rte_eth_bond_8023ad_conf *conf);
-void __vsym
-bond_mode_8023ad_conf_get_v20(struct rte_eth_dev *dev,
- struct rte_eth_bond_8023ad_conf *conf);
-void __vsym
-bond_mode_8023ad_conf_get_v21(struct rte_eth_dev *dev,
+bond_mode_8023ad_setup_v21(struct rte_eth_dev *dev,
struct rte_eth_bond_8023ad_conf *conf);
+BIND_DEFAULT_SYMBOL(bond_mode_8023ad_setup, _v21, 2.1);
+
+
/**
* @internal
diff --git a/drivers/net/bonding/rte_eth_bond_version.map
b/drivers/net/bonding/rte_eth_bond_version.map
index 328a423..0e144e3 100644
--- a/drivers/net/bonding/rte_eth_bond_version.map
+++ b/drivers/net/bonding/rte_eth_bond_version.map
@@ -2,6 +2,9 @@ DPDK_2.0 {
global:
rte_eth_bond_8023ad_conf_get;
+ rte_eth_bond_8023ad_ext_collect;
+ rte_eth_bond_8023ad_ext_distrib;
+ rte_eth_bond_8023ad_ext_slowtx;
rte_eth_bond_8023ad_setup;
rte_eth_bond_active_slaves_get;
rte_eth_bond_create;
@@ -17,9 +20,6 @@ DPDK_2.0 {
rte_eth_bond_slaves_get;
rte_eth_bond_xmit_policy_get;
rte_eth_bond_xmit_policy_set;
- rte_eth_bond_8023ad_ext_collect;
- rte_eth_bond_8023ad_ext_distrib;
- rte_eth_bond_8023ad_ext_slowtx;
local: *;
};
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH] doc: fix minor sphinx build warning
2015-07-02 11:52 9% [dpdk-dev] [PATCH] doc: fix minor sphinx build warning John McNamara
@ 2015-07-02 12:18 3% ` Thomas Monjalon
2015-07-02 13:28 0% ` Mcnamara, John
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-07-02 12:18 UTC (permalink / raw)
To: John McNamara; +Cc: dev
2015-07-02 12:52, John McNamara:
> Also added a RST label to the start of the doc to allow it
> to be linked to from other docs.
We don't really need to have a label at the top of the doc.
It can be linked with :doc: role:
dpdk.org/browse/dpdk/commit/?id=7cc2bdedd3812998078
But it could be useful in case new versioning chapters are added before
ABI guidelines.
In this case, the link referenced in the commit above should be updated.
> --- a/doc/guides/guidelines/versioning.rst
> +++ b/doc/guides/guidelines/versioning.rst
> @@ -1,3 +1,5 @@
> +.. abi_guidelines:
> +
> Managing ABI updates
> ====================
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH] doc: fix minor sphinx build warning
@ 2015-07-02 11:52 9% John McNamara
2015-07-02 12:18 3% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: John McNamara @ 2015-07-02 11:52 UTC (permalink / raw)
To: dev
Fix for a minor Sphinx build warning in the ABI guidelines docs:
versioning.rst:126: WARNING: Bullet list ends without a
blank line; unexpected unindent.
Also added a RST label to the start of the doc to allow it
to be linked to from other docs.
Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
doc/guides/guidelines/versioning.rst | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
index a1c9368..57db6fd 100644
--- a/doc/guides/guidelines/versioning.rst
+++ b/doc/guides/guidelines/versioning.rst
@@ -1,3 +1,5 @@
+.. abi_guidelines:
+
Managing ABI updates
====================
@@ -122,9 +124,9 @@ The macros exported are:
the linker to bind references to symbol ``b`` to the internal symbol
``b_e``.
-* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the fully
-qualified function ``p``, so that if a symbol becomes versioned, it can still be
-mapped back to the public symbol name.
+* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the
+ fully qualified function ``p``, so that if a symbol becomes versioned, it
+ can still be mapped back to the public symbol name.
Examples of ABI Macro use
-------------------------
--
1.8.1.4
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types
2015-07-02 1:30 0% ` Zhang, Helin
@ 2015-07-02 9:31 0% ` Olivier MATZ
2015-07-03 1:30 0% ` Zhang, Helin
0 siblings, 1 reply; 200+ results
From: Olivier MATZ @ 2015-07-02 9:31 UTC (permalink / raw)
To: Zhang, Helin, dev
Hi Helin,
On 07/02/2015 03:30 AM, Zhang, Helin wrote:
> Hi Oliver
>
> Thanks for your helps!
>
>> -----Original Message-----
>> From: Olivier MATZ [mailto:olivier.matz@6wind.com]
>> Sent: Tuesday, June 30, 2015 4:44 PM
>> To: Zhang, Helin; dev@dpdk.org
>> Cc: Cao, Waterman; Liang, Cunming; Liu, Jijiang; Ananyev, Konstantin; Richardson,
>> Bruce; yongwang@vmware.com; Wu, Jingjing
>> Subject: Re: [PATCH v8 03/18] mbuf: add definitions of unified packet types
>>
>> Hi Helin,
>>
>> This is greatly documented, thanks!
>> Please find a small comment below.
>>
>> On 06/23/2015 03:50 AM, Helin Zhang wrote:
>>> As there are only 6 bit flags in ol_flags for indicating packet types,
>>> which is not enough to describe all the possible packet types hardware
>>> can recognize. For example, i40e hardware can recognize more than 150
>>> packet types. Unified packet type is composed of L2 type, L3 type, L4
>>> type, tunnel type, inner L2 type, inner L3 type and inner L4 type
>>> fields, and can be stored in 'struct rte_mbuf' of 32 bits field
>>> 'packet_type'.
>>> To avoid breaking ABI compatibility, all the changes would be enabled
>>> by RTE_NEXT_ABI, which is disabled by default.
>>>
>>> [...]
>>> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
>>> index 0315561..0ee0c55 100644
>>> --- a/lib/librte_mbuf/rte_mbuf.h
>>> +++ b/lib/librte_mbuf/rte_mbuf.h
>>> @@ -201,6 +201,493 @@ extern "C" {
>>> /* Use final bit of flags to indicate a control mbuf */
>>> #define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control
>> data */
>>>
>>> +#ifdef RTE_NEXT_ABI
>>> +/*
>>> + * 32 bits are divided into several fields to mark packet types. Note
>>> +that
>>> + * each field is indexical.
>>> + * - Bit 3:0 is for L2 types.
>>> + * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
>>> + * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
>>> + * - Bit 15:12 is for tunnel types.
>>> + * - Bit 19:16 is for inner L2 types.
>>> + * - Bit 23:20 is for inner L3 types.
>>> + * - Bit 27:24 is for inner L4 types.
>>> + * - Bit 31:28 is reserved.
>>> + *
>>> + * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4,
>>> +RTE_PTYPE_L3_IPV4_EXT,
>>> + * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP,
>>> +RTE_PTYPE_L4_UDP
>>> + * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
>>> + *
>>> + * Note that L3 types values are selected for checking IPV4/IPV6
>>> +header from
>>> + * performance point of view. Reading annotations of
>>> +RTE_ETH_IS_IPV4_HDR and
>>> + * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
>>> + *
>>> + * Note that the packet types of the same packet recognized by
>>> +different
>>> + * hardware may be different, as different hardware may have
>>> +different
>>> + * capability of packet type recognition.
>>> + *
>>> + * examples:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=0x29
>>> + * | 'version'=6, 'next header'=0x3A
>>> + * | 'ICMPv6 header'>
>>> + * will be recognized on i40e hardware as packet type combination of,
>>> + * RTE_PTYPE_L2_MAC |
>>> + * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
>>> + * RTE_PTYPE_TUNNEL_IP |
>>> + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
>>> + * RTE_PTYPE_INNER_L4_ICMP.
>>> + *
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=0x2F
>>> + * | 'GRE header'
>>> + * | 'version'=6, 'next header'=0x11
>>> + * | 'UDP header'>
>>> + * will be recognized on i40e hardware as packet type combination of,
>>> + * RTE_PTYPE_L2_MAC |
>>> + * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
>>> + * RTE_PTYPE_TUNNEL_GRENAT |
>>> + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
>>> + * RTE_PTYPE_INNER_L4_UDP.
>>> + */
>>> +#define RTE_PTYPE_UNKNOWN 0x00000000
>>> +/**
>>> + * MAC (Media Access Control) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=[0x0800|0x86DD|others]> */
>>> +#define RTE_PTYPE_L2_MAC 0x00000001
>>
>> I'm wondering if RTE_PTYPE_L2_ETHER is not a better name?
> Ethernet includes both Data Link Layer and Physical Layer, while MAC is for Data Link
> Layer only. I would prefer to keep 'MAC' in the names, rather than 'ether'.
> Any opinions from others?
Just to precise what I'm saying: MAC is the interface between
the logical link and the physical layer. It is different
depending on the physical media (Ethernet, Token Ring, WLAN, ...).
Every packet has a MAC layer and I think "MAC" does not bring
any information.
Having "ETHER" in the name would inform the software that
it can expect an ethernet header. In the future, I would expect
to have more L2 types like PPP.
I also have another question about RTE_PTYPE_L2_MAC. You
describe it as "<'ether type'=[0x0800|0x86DD|others]>".
What is the meaning of "others"? Does it mean that it is
valid to set RTE_PTYPE_L2_MAC for any received packet?
For instance, an ARP packet. The driver has the choice
to set:
A- RTE_PTYPE_UNKNOWN: the driver does not know the L2 packet
type
B- RTE_PTYPE_L2_MAC: the driver knows it's an ethernet packet
(it should be the case for all received packets today as
dpdk only supports ethernet ports)
C- RTE_PTYPE_L2_ARP: the driver knows that the packet carries
an ARP header after the ethernet header.
Is it correct for a driver to always set B- for all received
packets?
Another thing that bothers me a bit is that L2_ARP, L2_LLDP,
L2_MAC_TIMESYNC, (...) are not really L2 types. The L2 type is
Ethernet. On the other hand, they are not L3 type either.
So, I have no other solution. The OSI model is probably a
bit too theorical, and we have to choose the solution that
is the most useful for the applications, even if it does not
absolutely matches the theory ;)
Regards,
Olivier
>
> Regards,
> Helin
>
>>
>>
>>> +/**
>>> + * MAC (Media Access Control) packet type for time sync.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x88F7>
>>> + */
>>> +#define RTE_PTYPE_L2_MAC_TIMESYNC 0x00000002
>>> +/**
>>> + * ARP (Address Resolution Protocol) packet type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0806>
>>> + */
>>> +#define RTE_PTYPE_L2_ARP 0x00000003
>>> +/**
>>> + * LLDP (Link Layer Discovery Protocol) packet type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x88CC>
>>> + */
>>> +#define RTE_PTYPE_L2_LLDP 0x00000004
>>
>> Maybe ETHER should appear in these names too, what do you think?
> Same as above.
>
>>
>>
>>
>>
>>> +/**
>>> + * Mask of layer 2 packet types.
>>> + * It is used for outer packet for tunneling cases.
>>> + */
>>> +#define RTE_PTYPE_L2_MASK 0x0000000f
>>> +/**
>>> + * IP (Internet Protocol) version 4 packet type.
>>> + * It is used for outer packet for tunneling cases, and does not
>>> +contain any
>>> + * header option.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'ihl'=5>
>>> + */
>>> +#define RTE_PTYPE_L3_IPV4 0x00000010
>>> +/**
>>> + * IP (Internet Protocol) version 4 packet type.
>>> + * It is used for outer packet for tunneling cases, and contains
>>> +header
>>> + * options.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'ihl'=[6-15], 'options'> */
>>> +#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
>>> +/**
>>> + * IP (Internet Protocol) version 6 packet type.
>>> + * It is used for outer packet for tunneling cases, and does not
>>> +contain any
>>> + * extension header.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=0x3B> */
>>> +#define RTE_PTYPE_L3_IPV6 0x00000040
>>> +/**
>>> + * IP (Internet Protocol) version 4 packet type.
>>> + * It is used for outer packet for tunneling cases, and may or maynot
>>> +contain
>>> + * header options.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'ihl'=[5-15], <'options'>> */
>>> +#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
>>> +/**
>>> + * IP (Internet Protocol) version 6 packet type.
>>> + * It is used for outer packet for tunneling cases, and contains
>>> +extension
>>> + * headers.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
>>> + * 'extension headers'>
>>> + */
>>> +#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
>>> +/**
>>> + * IP (Internet Protocol) version 6 packet type.
>>> + * It is used for outer packet for tunneling cases, and may or maynot
>>> +contain
>>> + * extension headers.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
>>> + * <'extension headers'>>
>>> + */
>>> +#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
>>> +/**
>>> + * Mask of layer 3 packet types.
>>> + * It is used for outer packet for tunneling cases.
>>> + */
>>> +#define RTE_PTYPE_L3_MASK 0x000000f0
>>> +/**
>>> + * TCP (Transmission Control Protocol) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=6, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=6>
>>> + */
>>> +#define RTE_PTYPE_L4_TCP 0x00000100
>>> +/**
>>> + * UDP (User Datagram Protocol) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=17, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=17>
>>> + */
>>> +#define RTE_PTYPE_L4_UDP 0x00000200
>>> +/**
>>> + * Fragmented IP (Internet Protocol) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * It refers to those packets of any IP types, which can be
>>> +recognized as
>>> + * fragmented. A fragmented packet cannot be recognized as any other
>>> +L4 types
>>> + * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP,
>>> +RTE_PTYPE_L4_ICMP,
>>> + * RTE_PTYPE_L4_NONFRAG).
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'MF'=1>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=44>
>>> + */
>>> +#define RTE_PTYPE_L4_FRAG 0x00000300
>>> +/**
>>> + * SCTP (Stream Control Transmission Protocol) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=132, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=132>
>>> + */
>>> +#define RTE_PTYPE_L4_SCTP 0x00000400
>>> +/**
>>> + * ICMP (Internet Control Message Protocol) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=1, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=1>
>>> + */
>>> +#define RTE_PTYPE_L4_ICMP 0x00000500
>>> +/**
>>> + * Non-fragmented IP (Internet Protocol) packet type.
>>> + * It is used for outer packet for tunneling cases.
>>> + *
>>> + * It refers to those packets of any IP types, while cannot be
>>> +recognized as
>>> + * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
>>> + * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'!=[6|17|44|132|1]> */
>>> +#define RTE_PTYPE_L4_NONFRAG 0x00000600
>>> +/**
>>> + * Mask of layer 4 packet types.
>>> + * It is used for outer packet for tunneling cases.
>>> + */
>>> +#define RTE_PTYPE_L4_MASK 0x00000f00
>>> +/**
>>> + * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=[4|41]>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=[4|41]> */
>>> +#define RTE_PTYPE_TUNNEL_IP 0x00001000
>>> +/**
>>> + * GRE (Generic Routing Encapsulation) tunneling packet type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=47>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=47>
>>> + */
>>> +#define RTE_PTYPE_TUNNEL_GRE 0x00002000
>>> +/**
>>> + * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=17
>>> + * | 'destination port'=4798>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=17
>>> + * | 'destination port'=4798>
>>> + */
>>> +#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
>>> +/**
>>> + * NVGRE (Network Virtualization using Generic Routing Encapsulation)
>>> +tunneling
>>> + * packet type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=47
>>> + * | 'protocol type'=0x6558>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=47
>>> + * | 'protocol type'=0x6558'>
>>> + */
>>> +#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
>>> +/**
>>> + * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet
>> type.
>>> + *
>>> + * Packet format:
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=17
>>> + * | 'destination port'=6081>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=17
>>> + * | 'destination port'=6081>
>>> + */
>>> +#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
>>> +/**
>>> + * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local
>>> +Area
>>> + * Network) or GRE (Generic Routing Encapsulation) could be
>>> +recognized as this
>>> + * packet type, if they can not be recognized independently as of
>>> +hardware
>>> + * capability.
>>> + */
>>> +#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
>>> +/**
>>> + * Mask of tunneling packet types.
>>> + */
>>> +#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
>>> +/**
>>> + * MAC (Media Access Control) packet type.
>>> + * It is used for inner packet type only.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=[0x800|0x86DD]>
>>> + */
>>> +#define RTE_PTYPE_INNER_L2_MAC 0x00010000
>>> +/**
>>> + * MAC (Media Access Control) packet type with VLAN (Virtual Local
>>> +Area
>>> + * Network) tag.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=[0x800|0x86DD], vlan=[1-4095]> */
>>> +#define RTE_PTYPE_INNER_L2_MAC_VLAN 0x00020000
>>> +/**
>>> + * Mask of inner layer 2 packet types.
>>> + */
>>> +#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
>>> +/**
>>> + * IP (Internet Protocol) version 4 packet type.
>>> + * It is used for inner packet only, and does not contain any header option.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'ihl'=5>
>>> + */
>>> +#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
>>> +/**
>>> + * IP (Internet Protocol) version 4 packet type.
>>> + * It is used for inner packet only, and contains header options.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'ihl'=[6-15], 'options'> */
>>> +#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
>>> +/**
>>> + * IP (Internet Protocol) version 6 packet type.
>>> + * It is used for inner packet only, and does not contain any extension header.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=0x3B> */
>>> +#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
>>> +/**
>>> + * IP (Internet Protocol) version 4 packet type.
>>> + * It is used for inner packet only, and may or maynot contain header options.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'ihl'=[5-15], <'options'>> */ #define
>>> +RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
>>> +/**
>>> + * IP (Internet Protocol) version 6 packet type.
>>> + * It is used for inner packet only, and contains extension headers.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
>>> + * 'extension headers'>
>>> + */
>>> +#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
>>> +/**
>>> + * IP (Internet Protocol) version 6 packet type.
>>> + * It is used for inner packet only, and may or maynot contain
>>> +extension
>>> + * headers.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
>>> + * <'extension headers'>>
>>> + */
>>> +#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
>>> +/**
>>> + * Mask of inner layer 3 packet types.
>>> + */
>>> +#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
>>> +/**
>>> + * TCP (Transmission Control Protocol) packet type.
>>> + * It is used for inner packet only.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=6, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=6>
>>> + */
>>> +#define RTE_PTYPE_INNER_L4_TCP 0x01000000
>>> +/**
>>> + * UDP (User Datagram Protocol) packet type.
>>> + * It is used for inner packet only.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=17, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=17>
>>> + */
>>> +#define RTE_PTYPE_INNER_L4_UDP 0x02000000
>>> +/**
>>> + * Fragmented IP (Internet Protocol) packet type.
>>> + * It is used for inner packet only, and may or maynot have layer 4 packet.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'MF'=1>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=44>
>>> + */
>>> +#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
>>> +/**
>>> + * SCTP (Stream Control Transmission Protocol) packet type.
>>> + * It is used for inner packet only.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=132, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=132>
>>> + */
>>> +#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
>>> +/**
>>> + * ICMP (Internet Control Message Protocol) packet type.
>>> + * It is used for inner packet only.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'=1, 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'=1>
>>> + */
>>> +#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
>>> +/**
>>> + * Non-fragmented IP (Internet Protocol) packet type.
>>> + * It is used for inner packet only, and may or maynot have other
>>> +unknown layer
>>> + * 4 packet types.
>>> + *
>>> + * Packet format (inner only):
>>> + * <'ether type'=0x0800
>>> + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
>>> + * or,
>>> + * <'ether type'=0x86DD
>>> + * | 'version'=6, 'next header'!=[6|17|44|132|1]> */
>>> +#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
>>> +/**
>>> + * Mask of inner layer 4 packet types.
>>> + */
>>> +#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
>>> +
>>> +/**
>>> + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4
>>> +types one by
>>> + * one, bit 4 is selected to be used for IPv4 only. Then checking bit
>>> +4 can
>>> + * determin if it is an IPV4 packet.
>>> + */
>>> +#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
>>> +
>>> +/**
>>> + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4
>>> +types one by
>>> + * one, bit 6 is selected to be used for IPv4 only. Then checking bit
>>> +6 can
>>> + * determin if it is an IPV4 packet.
>>> + */
>>> +#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
>>> +
>>> +/* Check if it is a tunneling packet */ #define
>>> +RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
>> #endif
>>> +/* RTE_NEXT_ABI */
>>> +
>>> /**
>>> * Get the name of a RX offload flag
>>> *
>>>
>
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v8 00/18] unified packet type
2015-06-23 16:13 0% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Ananyev, Konstantin
@ 2015-07-02 8:45 0% ` Liu, Yong
0 siblings, 0 replies; 200+ results
From: Liu, Yong @ 2015-07-02 8:45 UTC (permalink / raw)
To: Ananyev, Konstantin, Zhang, Helin, dev
Tested-by: Yong Liu <yong.liu@intel.com>
- Tested Commit: 7e1fa1de8a536c68f6af76cf8d222a9e948c93ba
- OS: Fedora20 3.15.5
- GCC: gcc version 4.8.3 20140911
- CPU: Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz
- NIC: Intel Corporation XL710 10-Gigabit SFI/SFP+ [8086:1572]
- NIC: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ [8086:10fb]
- NIC: Intel Corporation I350 Gigabit Network Connection [8086:1521]
- Default x86_64-native-linuxapp-gcc configuration
- Prerequisites: Enable CONFIG_RTE_NEXT_ABI in dpdk configuration
Disable CONFIG_RTE_IXGBE_INC_VECTOR in dpdk configuration
- Total 10 cases, 10 passed, 0 failed
- Case: L2 packet type detect
Description: check L2 only packet can be normally detected by Fortville
Command / instruction:
Start testpmd and enable rxonly verbose mode
./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 -- -i --txqflags=0x0
set fwd rxonly
set verbose 1
start
Send time sync packet and verify Timesync packet detected
Send ARP packet and verify ARP packet detected
Send LLDP packet and verify LLDP packet detected
- Case: IPv4&L4 packet type detect
Description: check L3 and L4 packet can be normally detected
Fortville did not detect whether packet contian ipv4 header options, so L3
type will be shown as IPV4_EXT_UNKNOWN
Command / instruction:
Start testpmd and enable rxonly verbose mode
Send IP only packet and verify L3 packet detected
Send IP+UDP packet and verify L3&L4 packet detected
Send IP+TCP packet and verify L3&L4 packet detected
Send IP+SCTP packet and verify L3&L4 packet detected
Send IP+ICMP packet and verify L3&L4 packet detected
Send IP fragment+TCP packet and verify L3&L4 packet detected
- Case: IPv6&L4 packet type detect
Description: check IPv6 and L4 packet can be normally detected
Fortville did not detect whether packet contian ipv6 extension options, so
L3 type will be shown as IPV6_EXT_UNKNOWN
Command / instruction:
Start testpmd and enable rxonly verbose mode
Send IPv6 only packet and verify L3 packet detected
Send IPv6+UDP packet and verify L3&L4 packet detected
Send IPv6+TCP packet and verify L3&L4 packet detected
Send IPv6 fragment+TCP packet and verify L3&L4 packet detected
- Case: IP in IPv4 tunnel packet type detect
Description: check tunnel packet can be normally detected by Fortville
Command / instruction:
Send IPv4+IPv4 fragment packet and verify tunnel packet detected
Send IPv4+IPv4 packet and verify tunnel packet detected
Send IPv4+IPv4+UDP packet and verify tunnel packet detected
Send IPv4+IPv4+TCP packet and verify tunnel packet detected
Send IPv4+IPv4+SCTP packet and verify tunnel packet detected
Send IPv4+IPv4+ICMP packet and verify tunnel packet detected
Send IPv4+IPv6 fragment packet and verify tunnel packet detected
Send IPv4+IPv6 packet and verify tunnel packet detected
Send IPv4+IPv6+UDP packet and verify tunnel packet detected
Send IPv4+IPv6+TCP packet and verify tunnel packet detected
Send IPv4+IPv6+SCTP packet and verify tunnel packet detected
Send IPv4+IPv6+ICMP packet and verify tunnel packet detected
- Case: IPv6 in IPv4 tunnel packet type detect by niantic
Description: check tunnel packet can be normally detected by Niantic
Niantic only can detect few types of ip in ip tunnel packets, this case
designed to test them.
Command / instruction:
Send IPv4+IPv6 packet and verify tunnel packet detected
Send IPv4+IPv6_EXT packet and verify tunnel packet detected
Send IPv4+IPv6+UDP packet and verify tunnel packet detected
Send IPv4+IPv6+TCP packet and verify tunnel packet detected
Send IPv4+IPv6_EXT+UDP packet and verify tunnel packet detected
Send IPv4+IPv6_EXT+TCP packet and verify tunnel packet detected
- Case: IP in IPv6 tunnel packet type detect
Description: check tunnel packet can be normally detected by Fortville
Command / instruction:
Send IPv6+IPv4 fragment packet and verify tunnel packet detected
Send IPv6+IPv4 packet and verify tunnel packet detected
Send IPv6+IPv4+UDP packet and verify tunnel packet detected
Send IPv6+IPv4+TCP packet and verify tunnel packet detected
Send IPv6+IPv4+SCTP packet and verify tunnel packet detected
Send IPv6+IPv4+ICMP packet and verify tunnel packet detected
Send IPv6+IPv6 fragment packet and verify tunnel packet detected
Send IPv6+IPv6 packet and verify tunnel packet detected
Send IPv6+IPv6+UDP packet and verify tunnel packet detected
Send IPv6+IPv6+TCP packet and verify tunnel packet detected
Send IPv6+IPv6+SCTP packet and verify tunnel packet detected
Send IPv6+IPv6+ICMP packet and verify tunnel packet detected
- Case: NVGRE tunnel packet type detect
Description: check tunnel packet can be normally detected by Fortville
Fortville did not distinguish GRE/Teredo/Vxlan packets, all those types
will be displayed as GRENAT
Command / instruction:
Send IPv4+NVGRE fragment packet and verify tunnel packet detected
Send IPV4+NVGRE+MAC packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv4 fragment packet and verify tunnel packet
detected
Send IPv4+NVGRE+MAC_VLAN+IPv4 packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv4+UDP packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv4+TCP packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv4+SCTP packet and verify tunnel packet
detected
Send IPv4+NVGRE+MAC_VLAN+IPv4+ICMP packet and verify tunnel packet
detected
Send IPv4+NVGRE+MAC_VLAN+IPv6+IPv6 fragment acket and verify tunnel packet
detected
Send IPv4+NVGRE+MAC_VLAN+IPv6 packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv6+UDP packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv6+TCP packet and verify tunnel packet detected
Send IPv4+NVGRE+MAC_VLAN+IPv6+SCTP packet and verify tunnel packet
detected
Send IPv4+NVGRE+MAC_VLAN+IPv6+ICMP packet and verify tunnel packet
detected
- Case: NVGRE in IPv6 tunnel packet type detect
Description: check tunnel packet can be normally detected by Fortville
Fortville did not distinguish GRE/Teredo/Vxlan packets, all those types
will be displayed as GRENAT
Command / instruction:
Send IPV6+NVGRE+MAC packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv4 fragment packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv4 packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv4+UDP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv4+TCP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv4+SCTP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv4+ICMP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv6 fragment packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv6 packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv6+UDP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv6+TCP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv6+SCTP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC+IPv6+ICMP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv4 fragment packet and verify tunnel packet
detected
Send IPV6+NVGRE+MAC_VLAN+IPv4 packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv4+UDP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv4+TCP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv4+SCTP packet and verify tunnel packet
detected
Send IPV6+NVGRE+MAC_VLAN+IPv4+ICMP packet and verify tunnel packet
detected
Send IPV6+NVGRE+MAC_VLAN+IPv6 fragment packet and verify tunnel packet
detected
Send IPV6+NVGRE+MAC_VLAN+IPv6 packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv6+UDP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv6+TCP packet and verify tunnel packet detected
Send IPV6+NVGRE+MAC_VLAN+IPv6+SCTP packet and verify tunnel packet
detected
Send IPV6+NVGRE+MAC_VLAN+IPv6+ICMP packet and verify tunnel packet
detected
Send IPV6+NVGRE+MAC_VLAN+IPv6 fragment packet and verify tunnel packet
detected
- Case: GRE tunnel packet type detect
Description: check tunnel packet can be normally detected by Fortville
Fortville did not distinguish GRE/Teredo/Vxlan packets, all those types
will be displayed as GRENAT
Command / instruction:
Send IPv4+GRE+IPv4 fragment packet and verify tunnel packet detected
Send IPv4+GRE+IPv4 packet and verify tunnel packet detected
Send IPv4+GRE+IPv4+UDP packet and verify tunnel packet detected
Send IPv4+GRE+IPv4+TCP packet and verify tunnel packet detected
Send IPv4+GRE+IPv4+SCTP packet and verify tunnel packet detected
Send IPv4+GRE+IPv4+ICMP packet and verify tunnel packet detected
Send IPv4+GRE packet and verify tunnel packet detected
- Case: Vxlan tunnel packet type detect
Description: check tunnel packet can be normally detected by Fortville
Fortville did not distinguish GRE/Teredo/Vxlan packets, all those types
will be displayed as GRENAT
Command / instruction:
Add vxlan tunnle port filter on receive port
rx_vxlan_port add 4789 0
Send IPv4+Vxlan+MAC+IPv4 fragment packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv4 packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv4+UDP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv4+TCP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv4+SCTP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv4+ICMP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv6 fragment packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv6 packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv6+UDP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv6+TCP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv6+SCTP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC+IPv6+ICMP packet and verify tunnel packet detected
Send IPv4+Vxlan+MAC packet and verify tunnel packet detected
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Ananyev, Konstantin
> Sent: Wednesday, June 24, 2015 12:14 AM
> To: Zhang, Helin; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v8 00/18] unified packet type
>
>
>
> > -----Original Message-----
> > From: Zhang, Helin
> > Sent: Tuesday, June 23, 2015 2:50 AM
> > To: dev@dpdk.org
> > Cc: Cao, Waterman; Liang, Cunming; Liu, Jijiang; Ananyev, Konstantin;
> Richardson, Bruce; yongwang@vmware.com;
> > olivier.matz@6wind.com; Wu, Jingjing; Zhang, Helin
> > Subject: [PATCH v8 00/18] unified packet type
> >
> > Currently only 6 bits which are stored in ol_flags are used to indicate
> the
> > packet types. This is not enough, as some NIC hardware can recognize
> quite
> > a lot of packet types, e.g i40e hardware can recognize more than 150
> packet
> > types. Hiding those packet types hides hardware offload capabilities
> which
> > could be quite useful for improving performance and for end users.
> > So an unified packet types are needed to support all possible PMDs. A 16
> > bits packet_type in mbuf structure can be changed to 32 bits and used
> for
> > this purpose. In addition, all packet types stored in ol_flag field
> should
> > be deleted at all, and 6 bits of ol_flags can be save as the benifit.
> >
> > Initially, 32 bits of packet_type can be divided into several sub fields
> to
> > indicate different packet type information of a packet. The initial
> design
> > is to divide those bits into fields for L2 types, L3 types, L4 types,
> tunnel
> > types, inner L2 types, inner L3 types and inner L4 types. All PMDs
> should
> > translate the offloaded packet types into these 7 fields of information,
> for
> > user applications.
> >
> > To avoid breaking ABI compatibility, currently all the code changes for
> > unified packet type are disabled at compile time by default. Users can
> enable
> > it manually by defining the macro of RTE_NEXT_ABI. The code changes will
> be
> > valid by default in a future release, and the old version will be
> deleted
> > accordingly, after the ABI change process is done.
> >
> > Note that this patch set should be integrated after another patch set
> for
> > '[PATCH v3 0/7] support i40e QinQ stripping and insertion', to clearly
> solve
> > the conflict during integration. As both patch sets modified 'struct
> rte_mbuf',
> > and the final layout of the 'struct rte_mbuf' is key to vectorized ixgbe
> PMD.
> >
> > v2 changes:
> > * Enlarged the packet_type field from 16 bits to 32 bits.
> > * Redefined the packet type sub-fields.
> > * Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf
> changes.
> > * Used redefined packet types and enlarged packet_type field for all
> PMDs
> > and corresponding applications.
> > * Removed changes in bond and its relevant application, as there is no
> need
> > at all according to the recent bond changes.
> >
> > v3 changes:
> > * Put the mbuf layout changes into a single patch.
> > * Put vector ixgbe changes right after mbuf changes.
> > * Disabled vector ixgbe PMD by default, as mbuf layout changed, and then
> > re-enabled it after vector ixgbe PMD updated.
> > * Put the definitions of unified packet type into a single patch.
> > * Minor bug fixes and enhancements in l3fwd example.
> >
> > v4 changes:
> > * Added detailed description of each packet types.
> > * Supported unified packet type of fm10k.
> > * Added printing logs of packet types of each received packet for rxonly
> > mode in testpmd.
> > * Removed several useless code lines which block packet type unification
> from
> > app/test/packet_burst_generator.c.
> >
> > v5 changes:
> > * Added more detailed description for each packet types, together with
> examples.
> > * Rolled back the macro definitions of RX packet flags, for ABI
> compitability.
> >
> > v6 changes:
> > * Disabled the code changes for unified packet type by default, to
> > avoid breaking ABI compatibility.
> >
> > v7 changes:
> > * Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
> > * Integrated with patch set for '[PATCH v3 0/7] support i40e QinQ
> stripping
> > and insertion', to clearly solve the conflicts during merging.
> >
> > v8 changes:
> > * Moved the field of 'vlan_tci_outer' in 'struct rte_mbuf' to the end of
> the 1st
> > cache line, to avoid breaking any vectorized PMD storing, as fields of
> > 'packet_type, pkt_len, data_len, vlan_tci, rss' should be in an
> contiguous 128
> > bits.
> >
> > Helin Zhang (18):
> > mbuf: redefine packet_type in rte_mbuf
> > ixgbe: support unified packet type in vectorized PMD
> > mbuf: add definitions of unified packet types
> > e1000: replace bit mask based packet type with unified packet type
> > ixgbe: replace bit mask based packet type with unified packet type
> > i40e: replace bit mask based packet type with unified packet type
> > enic: replace bit mask based packet type with unified packet type
> > vmxnet3: replace bit mask based packet type with unified packet type
> > fm10k: replace bit mask based packet type with unified packet type
> > app/test-pipeline: replace bit mask based packet type with unified
> > packet type
> > app/testpmd: replace bit mask based packet type with unified packet
> > type
> > app/test: Remove useless code
> > examples/ip_fragmentation: replace bit mask based packet type with
> > unified packet type
> > examples/ip_reassembly: replace bit mask based packet type with
> > unified packet type
> > examples/l3fwd-acl: replace bit mask based packet type with unified
> > packet type
> > examples/l3fwd-power: replace bit mask based packet type with unified
> > packet type
> > examples/l3fwd: replace bit mask based packet type with unified packet
> > type
> > mbuf: remove old packet type bit masks
> >
> > app/test-pipeline/pipeline_hash.c | 13 +
> > app/test-pmd/csumonly.c | 14 +
> > app/test-pmd/rxonly.c | 183 +++++++
> > app/test/packet_burst_generator.c | 6 +-
> > drivers/net/e1000/igb_rxtx.c | 102 ++++
> > drivers/net/enic/enic_main.c | 26 +
> > drivers/net/fm10k/fm10k_rxtx.c | 27 ++
> > drivers/net/i40e/i40e_rxtx.c | 528
> +++++++++++++++++++++
> > drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++
> > drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 ++-
> > drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 +
> > examples/ip_fragmentation/main.c | 9 +
> > examples/ip_reassembly/main.c | 9 +
> > examples/l3fwd-acl/main.c | 29 +-
> > examples/l3fwd-power/main.c | 8 +
> > examples/l3fwd/main.c | 123 ++++-
> > .../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 +
> > lib/librte_mbuf/rte_mbuf.c | 4 +
> > lib/librte_mbuf/rte_mbuf.h | 517
> ++++++++++++++++++++
> > 19 files changed, 1837 insertions(+), 13 deletions(-)
> >
> > --
>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
>
> > 1.9.3
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types
2015-06-30 8:43 0% ` Olivier MATZ
@ 2015-07-02 1:30 0% ` Zhang, Helin
2015-07-02 9:31 0% ` Olivier MATZ
0 siblings, 1 reply; 200+ results
From: Zhang, Helin @ 2015-07-02 1:30 UTC (permalink / raw)
To: Olivier MATZ, dev
Hi Oliver
Thanks for your helps!
> -----Original Message-----
> From: Olivier MATZ [mailto:olivier.matz@6wind.com]
> Sent: Tuesday, June 30, 2015 4:44 PM
> To: Zhang, Helin; dev@dpdk.org
> Cc: Cao, Waterman; Liang, Cunming; Liu, Jijiang; Ananyev, Konstantin; Richardson,
> Bruce; yongwang@vmware.com; Wu, Jingjing
> Subject: Re: [PATCH v8 03/18] mbuf: add definitions of unified packet types
>
> Hi Helin,
>
> This is greatly documented, thanks!
> Please find a small comment below.
>
> On 06/23/2015 03:50 AM, Helin Zhang wrote:
> > As there are only 6 bit flags in ol_flags for indicating packet types,
> > which is not enough to describe all the possible packet types hardware
> > can recognize. For example, i40e hardware can recognize more than 150
> > packet types. Unified packet type is composed of L2 type, L3 type, L4
> > type, tunnel type, inner L2 type, inner L3 type and inner L4 type
> > fields, and can be stored in 'struct rte_mbuf' of 32 bits field
> > 'packet_type'.
> > To avoid breaking ABI compatibility, all the changes would be enabled
> > by RTE_NEXT_ABI, which is disabled by default.
> >
> > [...]
> > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> > index 0315561..0ee0c55 100644
> > --- a/lib/librte_mbuf/rte_mbuf.h
> > +++ b/lib/librte_mbuf/rte_mbuf.h
> > @@ -201,6 +201,493 @@ extern "C" {
> > /* Use final bit of flags to indicate a control mbuf */
> > #define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control
> data */
> >
> > +#ifdef RTE_NEXT_ABI
> > +/*
> > + * 32 bits are divided into several fields to mark packet types. Note
> > +that
> > + * each field is indexical.
> > + * - Bit 3:0 is for L2 types.
> > + * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
> > + * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
> > + * - Bit 15:12 is for tunnel types.
> > + * - Bit 19:16 is for inner L2 types.
> > + * - Bit 23:20 is for inner L3 types.
> > + * - Bit 27:24 is for inner L4 types.
> > + * - Bit 31:28 is reserved.
> > + *
> > + * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4,
> > +RTE_PTYPE_L3_IPV4_EXT,
> > + * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP,
> > +RTE_PTYPE_L4_UDP
> > + * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
> > + *
> > + * Note that L3 types values are selected for checking IPV4/IPV6
> > +header from
> > + * performance point of view. Reading annotations of
> > +RTE_ETH_IS_IPV4_HDR and
> > + * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
> > + *
> > + * Note that the packet types of the same packet recognized by
> > +different
> > + * hardware may be different, as different hardware may have
> > +different
> > + * capability of packet type recognition.
> > + *
> > + * examples:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=0x29
> > + * | 'version'=6, 'next header'=0x3A
> > + * | 'ICMPv6 header'>
> > + * will be recognized on i40e hardware as packet type combination of,
> > + * RTE_PTYPE_L2_MAC |
> > + * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
> > + * RTE_PTYPE_TUNNEL_IP |
> > + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
> > + * RTE_PTYPE_INNER_L4_ICMP.
> > + *
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=0x2F
> > + * | 'GRE header'
> > + * | 'version'=6, 'next header'=0x11
> > + * | 'UDP header'>
> > + * will be recognized on i40e hardware as packet type combination of,
> > + * RTE_PTYPE_L2_MAC |
> > + * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
> > + * RTE_PTYPE_TUNNEL_GRENAT |
> > + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
> > + * RTE_PTYPE_INNER_L4_UDP.
> > + */
> > +#define RTE_PTYPE_UNKNOWN 0x00000000
> > +/**
> > + * MAC (Media Access Control) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * Packet format:
> > + * <'ether type'=[0x0800|0x86DD|others]> */
> > +#define RTE_PTYPE_L2_MAC 0x00000001
>
> I'm wondering if RTE_PTYPE_L2_ETHER is not a better name?
Ethernet includes both Data Link Layer and Physical Layer, while MAC is for Data Link
Layer only. I would prefer to keep 'MAC' in the names, rather than 'ether'.
Any opinions from others?
Regards,
Helin
>
>
> > +/**
> > + * MAC (Media Access Control) packet type for time sync.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x88F7>
> > + */
> > +#define RTE_PTYPE_L2_MAC_TIMESYNC 0x00000002
> > +/**
> > + * ARP (Address Resolution Protocol) packet type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0806>
> > + */
> > +#define RTE_PTYPE_L2_ARP 0x00000003
> > +/**
> > + * LLDP (Link Layer Discovery Protocol) packet type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x88CC>
> > + */
> > +#define RTE_PTYPE_L2_LLDP 0x00000004
>
> Maybe ETHER should appear in these names too, what do you think?
Same as above.
>
>
>
>
> > +/**
> > + * Mask of layer 2 packet types.
> > + * It is used for outer packet for tunneling cases.
> > + */
> > +#define RTE_PTYPE_L2_MASK 0x0000000f
> > +/**
> > + * IP (Internet Protocol) version 4 packet type.
> > + * It is used for outer packet for tunneling cases, and does not
> > +contain any
> > + * header option.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'ihl'=5>
> > + */
> > +#define RTE_PTYPE_L3_IPV4 0x00000010
> > +/**
> > + * IP (Internet Protocol) version 4 packet type.
> > + * It is used for outer packet for tunneling cases, and contains
> > +header
> > + * options.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'ihl'=[6-15], 'options'> */
> > +#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
> > +/**
> > + * IP (Internet Protocol) version 6 packet type.
> > + * It is used for outer packet for tunneling cases, and does not
> > +contain any
> > + * extension header.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=0x3B> */
> > +#define RTE_PTYPE_L3_IPV6 0x00000040
> > +/**
> > + * IP (Internet Protocol) version 4 packet type.
> > + * It is used for outer packet for tunneling cases, and may or maynot
> > +contain
> > + * header options.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'ihl'=[5-15], <'options'>> */
> > +#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
> > +/**
> > + * IP (Internet Protocol) version 6 packet type.
> > + * It is used for outer packet for tunneling cases, and contains
> > +extension
> > + * headers.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> > + * 'extension headers'>
> > + */
> > +#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
> > +/**
> > + * IP (Internet Protocol) version 6 packet type.
> > + * It is used for outer packet for tunneling cases, and may or maynot
> > +contain
> > + * extension headers.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> > + * <'extension headers'>>
> > + */
> > +#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
> > +/**
> > + * Mask of layer 3 packet types.
> > + * It is used for outer packet for tunneling cases.
> > + */
> > +#define RTE_PTYPE_L3_MASK 0x000000f0
> > +/**
> > + * TCP (Transmission Control Protocol) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=6, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=6>
> > + */
> > +#define RTE_PTYPE_L4_TCP 0x00000100
> > +/**
> > + * UDP (User Datagram Protocol) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=17, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=17>
> > + */
> > +#define RTE_PTYPE_L4_UDP 0x00000200
> > +/**
> > + * Fragmented IP (Internet Protocol) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * It refers to those packets of any IP types, which can be
> > +recognized as
> > + * fragmented. A fragmented packet cannot be recognized as any other
> > +L4 types
> > + * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP,
> > +RTE_PTYPE_L4_ICMP,
> > + * RTE_PTYPE_L4_NONFRAG).
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'MF'=1>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=44>
> > + */
> > +#define RTE_PTYPE_L4_FRAG 0x00000300
> > +/**
> > + * SCTP (Stream Control Transmission Protocol) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=132, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=132>
> > + */
> > +#define RTE_PTYPE_L4_SCTP 0x00000400
> > +/**
> > + * ICMP (Internet Control Message Protocol) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=1, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=1>
> > + */
> > +#define RTE_PTYPE_L4_ICMP 0x00000500
> > +/**
> > + * Non-fragmented IP (Internet Protocol) packet type.
> > + * It is used for outer packet for tunneling cases.
> > + *
> > + * It refers to those packets of any IP types, while cannot be
> > +recognized as
> > + * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
> > + * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'!=[6|17|44|132|1]> */
> > +#define RTE_PTYPE_L4_NONFRAG 0x00000600
> > +/**
> > + * Mask of layer 4 packet types.
> > + * It is used for outer packet for tunneling cases.
> > + */
> > +#define RTE_PTYPE_L4_MASK 0x00000f00
> > +/**
> > + * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=[4|41]>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=[4|41]> */
> > +#define RTE_PTYPE_TUNNEL_IP 0x00001000
> > +/**
> > + * GRE (Generic Routing Encapsulation) tunneling packet type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=47>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=47>
> > + */
> > +#define RTE_PTYPE_TUNNEL_GRE 0x00002000
> > +/**
> > + * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=17
> > + * | 'destination port'=4798>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=17
> > + * | 'destination port'=4798>
> > + */
> > +#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
> > +/**
> > + * NVGRE (Network Virtualization using Generic Routing Encapsulation)
> > +tunneling
> > + * packet type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=47
> > + * | 'protocol type'=0x6558>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=47
> > + * | 'protocol type'=0x6558'>
> > + */
> > +#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
> > +/**
> > + * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet
> type.
> > + *
> > + * Packet format:
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=17
> > + * | 'destination port'=6081>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=17
> > + * | 'destination port'=6081>
> > + */
> > +#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
> > +/**
> > + * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local
> > +Area
> > + * Network) or GRE (Generic Routing Encapsulation) could be
> > +recognized as this
> > + * packet type, if they can not be recognized independently as of
> > +hardware
> > + * capability.
> > + */
> > +#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
> > +/**
> > + * Mask of tunneling packet types.
> > + */
> > +#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
> > +/**
> > + * MAC (Media Access Control) packet type.
> > + * It is used for inner packet type only.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=[0x800|0x86DD]>
> > + */
> > +#define RTE_PTYPE_INNER_L2_MAC 0x00010000
> > +/**
> > + * MAC (Media Access Control) packet type with VLAN (Virtual Local
> > +Area
> > + * Network) tag.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=[0x800|0x86DD], vlan=[1-4095]> */
> > +#define RTE_PTYPE_INNER_L2_MAC_VLAN 0x00020000
> > +/**
> > + * Mask of inner layer 2 packet types.
> > + */
> > +#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
> > +/**
> > + * IP (Internet Protocol) version 4 packet type.
> > + * It is used for inner packet only, and does not contain any header option.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'ihl'=5>
> > + */
> > +#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
> > +/**
> > + * IP (Internet Protocol) version 4 packet type.
> > + * It is used for inner packet only, and contains header options.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'ihl'=[6-15], 'options'> */
> > +#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
> > +/**
> > + * IP (Internet Protocol) version 6 packet type.
> > + * It is used for inner packet only, and does not contain any extension header.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=0x3B> */
> > +#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
> > +/**
> > + * IP (Internet Protocol) version 4 packet type.
> > + * It is used for inner packet only, and may or maynot contain header options.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'ihl'=[5-15], <'options'>> */ #define
> > +RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
> > +/**
> > + * IP (Internet Protocol) version 6 packet type.
> > + * It is used for inner packet only, and contains extension headers.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> > + * 'extension headers'>
> > + */
> > +#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
> > +/**
> > + * IP (Internet Protocol) version 6 packet type.
> > + * It is used for inner packet only, and may or maynot contain
> > +extension
> > + * headers.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> > + * <'extension headers'>>
> > + */
> > +#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
> > +/**
> > + * Mask of inner layer 3 packet types.
> > + */
> > +#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
> > +/**
> > + * TCP (Transmission Control Protocol) packet type.
> > + * It is used for inner packet only.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=6, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=6>
> > + */
> > +#define RTE_PTYPE_INNER_L4_TCP 0x01000000
> > +/**
> > + * UDP (User Datagram Protocol) packet type.
> > + * It is used for inner packet only.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=17, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=17>
> > + */
> > +#define RTE_PTYPE_INNER_L4_UDP 0x02000000
> > +/**
> > + * Fragmented IP (Internet Protocol) packet type.
> > + * It is used for inner packet only, and may or maynot have layer 4 packet.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'MF'=1>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=44>
> > + */
> > +#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
> > +/**
> > + * SCTP (Stream Control Transmission Protocol) packet type.
> > + * It is used for inner packet only.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=132, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=132>
> > + */
> > +#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
> > +/**
> > + * ICMP (Internet Control Message Protocol) packet type.
> > + * It is used for inner packet only.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'=1, 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'=1>
> > + */
> > +#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
> > +/**
> > + * Non-fragmented IP (Internet Protocol) packet type.
> > + * It is used for inner packet only, and may or maynot have other
> > +unknown layer
> > + * 4 packet types.
> > + *
> > + * Packet format (inner only):
> > + * <'ether type'=0x0800
> > + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
> > + * or,
> > + * <'ether type'=0x86DD
> > + * | 'version'=6, 'next header'!=[6|17|44|132|1]> */
> > +#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
> > +/**
> > + * Mask of inner layer 4 packet types.
> > + */
> > +#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
> > +
> > +/**
> > + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4
> > +types one by
> > + * one, bit 4 is selected to be used for IPv4 only. Then checking bit
> > +4 can
> > + * determin if it is an IPV4 packet.
> > + */
> > +#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
> > +
> > +/**
> > + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4
> > +types one by
> > + * one, bit 6 is selected to be used for IPv4 only. Then checking bit
> > +6 can
> > + * determin if it is an IPV4 packet.
> > + */
> > +#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
> > +
> > +/* Check if it is a tunneling packet */ #define
> > +RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
> #endif
> > +/* RTE_NEXT_ABI */
> > +
> > /**
> > * Get the name of a RX offload flag
> > *
> >
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping
2015-06-29 13:42 4% [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping John McNamara
2015-06-29 13:42 14% ` [dpdk-dev] [PATCH v2 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
@ 2015-07-02 1:24 0% ` Lu, Wenzhuo
2015-07-02 15:16 4% ` [dpdk-dev] [PATCH v3 " John McNamara
2 siblings, 0 replies; 200+ results
From: Lu, Wenzhuo @ 2015-07-02 1:24 UTC (permalink / raw)
To: Mcnamara, John, dev
Hi,
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of John McNamara
> Sent: Monday, June 29, 2015 9:42 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588
> timestamping
>
> This patchset adds ethdev API to enable and read IEEE1588/802.1AS PTP
> timestamps from devices that support it. The following functions are added:
>
> rte_eth_timesync_enable()
> rte_eth_timesync_disable()
> rte_eth_timesync_read_rx_timestamp()
> rte_eth_timesync_read_tx_timestamp()
>
> The "ieee1588" forwarding mode in testpmd is also refactored to demonstrate
> the new API and to clean up the code.
>
> Adds support for igb, ixgbe and i40e.
>
>
> V2:
> * Added i40e support.
>
> * Renamed ethdev functions from rte_eth_ieee15888_*() to
> rte_eth_timesync_*()
> since 802.1AS can be supported through the same interfaces.
>
> V1:
> * Initial version for
>
> John McNamara (7):
> ethdev: add support for ieee1588 timestamping
> e1000: add support for ieee1588 timestamping
> ixgbe: add support for ieee1588 timestamping
> i40e: add support for ieee1588 timestamping
> app/testpmd: refactor ieee1588 forwarding
> doc: document ieee1588 forwarding mode
> abi: announce mbuf addition for ieee1588 in DPDK 2.2
>
> app/test-pmd/ieee1588fwd.c | 466 ++--------------------------
> doc/guides/rel_notes/abi.rst | 5 +
> doc/guides/testpmd_app_ug/run_app.rst | 2 +-
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 2 +
> drivers/net/e1000/igb_ethdev.c | 115 +++++++
> drivers/net/i40e/i40e_ethdev.c | 143 +++++++++
> drivers/net/i40e/i40e_rxtx.c | 39 ++-
> drivers/net/ixgbe/ixgbe_ethdev.c | 122 ++++++++
> lib/librte_ether/rte_ethdev.c | 70 ++++-
> lib/librte_ether/rte_ethdev.h | 90 +++++-
> lib/librte_ether/rte_ether_version.map | 4 +
> 11 files changed, 615 insertions(+), 443 deletions(-)
>
> --
> 1.8.1.4
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] rte_lpm4 with expanded next hop support now available
2015-07-01 11:20 4% ` Bruce Richardson
@ 2015-07-01 15:59 0% ` Matthew Hall
0 siblings, 0 replies; 200+ results
From: Matthew Hall @ 2015-07-01 15:59 UTC (permalink / raw)
To: Bruce Richardson; +Cc: <dev@dpdk.org>
On Jul 1, 2015, at 4:20 AM, Bruce Richardson <bruce.richardson@intel.com> wrote:
> Could you maybe send a patch (or set) with all your changes in it here for us
> to look at? [I did look at it in github, but I'm not very familiar with github
> and the changes seem to be spread over a whole series of commits]
Here is a view of the specific commits:
https://github.com/megahall/dpdk_mhall/compare/megahall/lpm-expansion
I'll work on emails when I get a moment. I was hoping since the branch is open to all for download someone could sync it and try it in an environment that has some kind of performance tests / known results for the self-tests as my development setup is not that great compared to some of the other DPDK engineers out there.
> In terms of ABI issues, the overall function set for lpm4 library is not that
> big, so it may be possible to maintain old a new copies of the functions in parallel
> for one release, and solve the ABI issues that way. I'm quite keen to get these
> changes in, since I think being limited to 255 next hops is quite a limitation
> for many cases.
Sounds good.
> A final interesting suggestion I might throw out, is: can we make the lpm library
> configurable in that it can use either 8-bit, 16/24 bit or even pointer based
> next hops (I won't say 64-bit, as for pointers we might be able to get away
> with less than 64-bits being stored)? Would such a thing be useful to people?
I think this could be pretty nice, the tricky part is that, at least in the version Vladimir and Stephen helped me cook up, a lot of bitfield trickery was involved. So we'd need to switch away from bitfields to something a bit more flexible or easy to work with when variable configuration comes into the picture. Also not sure how it'd work at runtime versus compilation, etc. You guys know more than me about this stuff I think.
Matthew.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps
2015-06-26 12:59 3% [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps Maryam Tahhan
2015-06-26 12:59 9% ` [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs Maryam Tahhan
@ 2015-07-01 14:27 0% ` Tahhan, Maryam
1 sibling, 0 replies; 200+ results
From: Tahhan, Maryam @ 2015-07-01 14:27 UTC (permalink / raw)
To: dev, Olivier MATZ
> This patch set implements xstats_get() and xstats_reset() in dev_ops for ixgbe
> to expose detailed error statistics to DPDK applications. The dump_cfg
> application was extended to demonstrate the usage of retrieving statistics for
> DPDK interfaces and renamed to proc_info in order reflect this new
> functionality. This patch set also removes non generic statistics from the
> statistics strings at the ethdev level and marks the relevant registers as
> depricated in struct rte_eth_stats.
>
> v2:
> - Fixed patch dependencies.
> - Broke down patches into smaller logical changes.
>
> v3:
> - Removes non-generic stats fields in rte_stats_strings and deprecates
> the fields related to them in struct rte_eth_stats.
> - Modifies rte_eth_xstats_get() to return generic stats and extended stats.
>
> Maryam Tahhan (7):
> ixgbe: move stats register reads to a new function
> ixgbe: add functions to get and reset xstats
> ethdev: expose extended error stats
> ethdev: remove HW specific stats in stats structs
> ixgbe: add NIC specific stats removed from ethdev
> app: remove dump_cfg
> app: add a new app proc_info
>
> MAINTAINERS | 4 +
> app/Makefile | 2 +-
> app/dump_cfg/Makefile | 45 ----
> app/dump_cfg/main.c | 92 -------
> app/proc_info/Makefile | 45 ++++
> app/proc_info/main.c | 512
> +++++++++++++++++++++++++++++++++++++++
> doc/guides/rel_notes/abi.rst | 11 +
> drivers/net/ixgbe/ixgbe_ethdev.c | 192 ++++++++++++---
> lib/librte_ether/rte_ethdev.c | 29 ++-
> lib/librte_ether/rte_ethdev.h | 30 ++-
> mk/rte.sdktest.mk | 4 +-
> 11 files changed, 762 insertions(+), 204 deletions(-) delete mode 100644
> app/dump_cfg/Makefile delete mode 100644 app/dump_cfg/main.c create
> mode 100644 app/proc_info/Makefile create mode 100644
> app/proc_info/main.c
>
> --
> 1.9.3
Hi Olivier,
I posted a new patch set with the suggested mods. Let me know if there are any issues.
Thanks in advance.
Best Regards,
Maryam
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] rte_lpm4 with expanded next hop support now available
2015-07-01 6:18 3% [dpdk-dev] rte_lpm4 with expanded next hop support now available Matthew Hall
@ 2015-07-01 11:20 4% ` Bruce Richardson
2015-07-01 15:59 0% ` Matthew Hall
0 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2015-07-01 11:20 UTC (permalink / raw)
To: Matthew Hall; +Cc: <dev@dpdk.org>
On Tue, Jun 30, 2015 at 11:18:35PM -0700, Matthew Hall wrote:
> Hello,
>
> Based on the wonderful assistance from Vladimir and Stephen and a close friend of mine that is a hypervisor developer who helped me reverse engineer and rewrite rte_lpm_lookupx4, I have got a known-working version of rte_lpm4 with expanded 24 bit next hop support available here:
>
> https://github.com/megahall/dpdk_mhall/tree/megahall/lpm-expansion
>
> I'm going to be working on rte_lpm6 next, it seems to take a whole ton of memory to run the self-test, if anybody knows how much that would help, as it seems to run out when I tried it.
>
> Sadly this change is not ABI compatible or performance compatible with the original rte_lpm because I had to hack on the bitwise layout to get more data in there, and it will run maybe 50% slower because it has to access some more memory.
>
> Despite all this I'd really like to do the right thing find a way to contribute it back, perhaps as a second kind of rte_lpm, so I wouldn't be the only person using it and forking the code when I already met several others who needed it. I could use some ideas how to handle the situation.
>
> Matthew.
Could you maybe send a patch (or set) with all your changes in it here for us
to look at? [I did look at it in github, but I'm not very familiar with github
and the changes seem to be spread over a whole series of commits]
In terms of ABI issues, the overall function set for lpm4 library is not that
big, so it may be possible to maintain old a new copies of the functions in parallel
for one release, and solve the ABI issues that way. I'm quite keen to get these
changes in, since I think being limited to 255 next hops is quite a limitation
for many cases.
A final interesting suggestion I might throw out, is: can we make the lpm library
configurable in that it can use either 8-bit, 16/24 bit or even pointer based
next hops (I won't say 64-bit, as for pointers we might be able to get away
with less than 64-bits being stored)? Would such a thing be useful to people?
Regards,
/Bruce
^ permalink raw reply [relevance 4%]
* [dpdk-dev] rte_lpm4 with expanded next hop support now available
@ 2015-07-01 6:18 3% Matthew Hall
2015-07-01 11:20 4% ` Bruce Richardson
0 siblings, 1 reply; 200+ results
From: Matthew Hall @ 2015-07-01 6:18 UTC (permalink / raw)
To: <dev@dpdk.org>
Hello,
Based on the wonderful assistance from Vladimir and Stephen and a close friend of mine that is a hypervisor developer who helped me reverse engineer and rewrite rte_lpm_lookupx4, I have got a known-working version of rte_lpm4 with expanded 24 bit next hop support available here:
https://github.com/megahall/dpdk_mhall/tree/megahall/lpm-expansion
I'm going to be working on rte_lpm6 next, it seems to take a whole ton of memory to run the self-test, if anybody knows how much that would help, as it seems to run out when I tried it.
Sadly this change is not ABI compatible or performance compatible with the original rte_lpm because I had to hack on the bitwise layout to get more data in there, and it will run maybe 50% slower because it has to access some more memory.
Despite all this I'd really like to do the right thing find a way to contribute it back, perhaps as a second kind of rte_lpm, so I wouldn't be the only person using it and forking the code when I already met several others who needed it. I could use some ideas how to handle the situation.
Matthew.
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types Helin Zhang
@ 2015-06-30 8:43 0% ` Olivier MATZ
2015-07-02 1:30 0% ` Zhang, Helin
0 siblings, 1 reply; 200+ results
From: Olivier MATZ @ 2015-06-30 8:43 UTC (permalink / raw)
To: Helin Zhang, dev
Hi Helin,
This is greatly documented, thanks!
Please find a small comment below.
On 06/23/2015 03:50 AM, Helin Zhang wrote:
> As there are only 6 bit flags in ol_flags for indicating packet
> types, which is not enough to describe all the possible packet
> types hardware can recognize. For example, i40e hardware can
> recognize more than 150 packet types. Unified packet type is
> composed of L2 type, L3 type, L4 type, tunnel type, inner L2 type,
> inner L3 type and inner L4 type fields, and can be stored in
> 'struct rte_mbuf' of 32 bits field 'packet_type'.
> To avoid breaking ABI compatibility, all the changes would be
> enabled by RTE_NEXT_ABI, which is disabled by default.
>
> [...]
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> index 0315561..0ee0c55 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -201,6 +201,493 @@ extern "C" {
> /* Use final bit of flags to indicate a control mbuf */
> #define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control data */
>
> +#ifdef RTE_NEXT_ABI
> +/*
> + * 32 bits are divided into several fields to mark packet types. Note that
> + * each field is indexical.
> + * - Bit 3:0 is for L2 types.
> + * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
> + * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
> + * - Bit 15:12 is for tunnel types.
> + * - Bit 19:16 is for inner L2 types.
> + * - Bit 23:20 is for inner L3 types.
> + * - Bit 27:24 is for inner L4 types.
> + * - Bit 31:28 is reserved.
> + *
> + * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT,
> + * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP
> + * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
> + *
> + * Note that L3 types values are selected for checking IPV4/IPV6 header from
> + * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and
> + * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
> + *
> + * Note that the packet types of the same packet recognized by different
> + * hardware may be different, as different hardware may have different
> + * capability of packet type recognition.
> + *
> + * examples:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=0x29
> + * | 'version'=6, 'next header'=0x3A
> + * | 'ICMPv6 header'>
> + * will be recognized on i40e hardware as packet type combination of,
> + * RTE_PTYPE_L2_MAC |
> + * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
> + * RTE_PTYPE_TUNNEL_IP |
> + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
> + * RTE_PTYPE_INNER_L4_ICMP.
> + *
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=0x2F
> + * | 'GRE header'
> + * | 'version'=6, 'next header'=0x11
> + * | 'UDP header'>
> + * will be recognized on i40e hardware as packet type combination of,
> + * RTE_PTYPE_L2_MAC |
> + * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
> + * RTE_PTYPE_TUNNEL_GRENAT |
> + * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
> + * RTE_PTYPE_INNER_L4_UDP.
> + */
> +#define RTE_PTYPE_UNKNOWN 0x00000000
> +/**
> + * MAC (Media Access Control) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * Packet format:
> + * <'ether type'=[0x0800|0x86DD|others]>
> + */
> +#define RTE_PTYPE_L2_MAC 0x00000001
I'm wondering if RTE_PTYPE_L2_ETHER is not a better name?
> +/**
> + * MAC (Media Access Control) packet type for time sync.
> + *
> + * Packet format:
> + * <'ether type'=0x88F7>
> + */
> +#define RTE_PTYPE_L2_MAC_TIMESYNC 0x00000002
> +/**
> + * ARP (Address Resolution Protocol) packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x0806>
> + */
> +#define RTE_PTYPE_L2_ARP 0x00000003
> +/**
> + * LLDP (Link Layer Discovery Protocol) packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x88CC>
> + */
> +#define RTE_PTYPE_L2_LLDP 0x00000004
Maybe ETHER should appear in these names too, what do you think?
> +/**
> + * Mask of layer 2 packet types.
> + * It is used for outer packet for tunneling cases.
> + */
> +#define RTE_PTYPE_L2_MASK 0x0000000f
> +/**
> + * IP (Internet Protocol) version 4 packet type.
> + * It is used for outer packet for tunneling cases, and does not contain any
> + * header option.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'ihl'=5>
> + */
> +#define RTE_PTYPE_L3_IPV4 0x00000010
> +/**
> + * IP (Internet Protocol) version 4 packet type.
> + * It is used for outer packet for tunneling cases, and contains header
> + * options.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'ihl'=[6-15], 'options'>
> + */
> +#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
> +/**
> + * IP (Internet Protocol) version 6 packet type.
> + * It is used for outer packet for tunneling cases, and does not contain any
> + * extension header.
> + *
> + * Packet format:
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=0x3B>
> + */
> +#define RTE_PTYPE_L3_IPV6 0x00000040
> +/**
> + * IP (Internet Protocol) version 4 packet type.
> + * It is used for outer packet for tunneling cases, and may or maynot contain
> + * header options.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'ihl'=[5-15], <'options'>>
> + */
> +#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
> +/**
> + * IP (Internet Protocol) version 6 packet type.
> + * It is used for outer packet for tunneling cases, and contains extension
> + * headers.
> + *
> + * Packet format:
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> + * 'extension headers'>
> + */
> +#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
> +/**
> + * IP (Internet Protocol) version 6 packet type.
> + * It is used for outer packet for tunneling cases, and may or maynot contain
> + * extension headers.
> + *
> + * Packet format:
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> + * <'extension headers'>>
> + */
> +#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
> +/**
> + * Mask of layer 3 packet types.
> + * It is used for outer packet for tunneling cases.
> + */
> +#define RTE_PTYPE_L3_MASK 0x000000f0
> +/**
> + * TCP (Transmission Control Protocol) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=6, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=6>
> + */
> +#define RTE_PTYPE_L4_TCP 0x00000100
> +/**
> + * UDP (User Datagram Protocol) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=17, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=17>
> + */
> +#define RTE_PTYPE_L4_UDP 0x00000200
> +/**
> + * Fragmented IP (Internet Protocol) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * It refers to those packets of any IP types, which can be recognized as
> + * fragmented. A fragmented packet cannot be recognized as any other L4 types
> + * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP,
> + * RTE_PTYPE_L4_NONFRAG).
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'MF'=1>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=44>
> + */
> +#define RTE_PTYPE_L4_FRAG 0x00000300
> +/**
> + * SCTP (Stream Control Transmission Protocol) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=132, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=132>
> + */
> +#define RTE_PTYPE_L4_SCTP 0x00000400
> +/**
> + * ICMP (Internet Control Message Protocol) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=1, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=1>
> + */
> +#define RTE_PTYPE_L4_ICMP 0x00000500
> +/**
> + * Non-fragmented IP (Internet Protocol) packet type.
> + * It is used for outer packet for tunneling cases.
> + *
> + * It refers to those packets of any IP types, while cannot be recognized as
> + * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
> + * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'!=[6|17|44|132|1]>
> + */
> +#define RTE_PTYPE_L4_NONFRAG 0x00000600
> +/**
> + * Mask of layer 4 packet types.
> + * It is used for outer packet for tunneling cases.
> + */
> +#define RTE_PTYPE_L4_MASK 0x00000f00
> +/**
> + * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=[4|41]>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=[4|41]>
> + */
> +#define RTE_PTYPE_TUNNEL_IP 0x00001000
> +/**
> + * GRE (Generic Routing Encapsulation) tunneling packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=47>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=47>
> + */
> +#define RTE_PTYPE_TUNNEL_GRE 0x00002000
> +/**
> + * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=17
> + * | 'destination port'=4798>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=17
> + * | 'destination port'=4798>
> + */
> +#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
> +/**
> + * NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling
> + * packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=47
> + * | 'protocol type'=0x6558>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=47
> + * | 'protocol type'=0x6558'>
> + */
> +#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
> +/**
> + * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type.
> + *
> + * Packet format:
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=17
> + * | 'destination port'=6081>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=17
> + * | 'destination port'=6081>
> + */
> +#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
> +/**
> + * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area
> + * Network) or GRE (Generic Routing Encapsulation) could be recognized as this
> + * packet type, if they can not be recognized independently as of hardware
> + * capability.
> + */
> +#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
> +/**
> + * Mask of tunneling packet types.
> + */
> +#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
> +/**
> + * MAC (Media Access Control) packet type.
> + * It is used for inner packet type only.
> + *
> + * Packet format (inner only):
> + * <'ether type'=[0x800|0x86DD]>
> + */
> +#define RTE_PTYPE_INNER_L2_MAC 0x00010000
> +/**
> + * MAC (Media Access Control) packet type with VLAN (Virtual Local Area
> + * Network) tag.
> + *
> + * Packet format (inner only):
> + * <'ether type'=[0x800|0x86DD], vlan=[1-4095]>
> + */
> +#define RTE_PTYPE_INNER_L2_MAC_VLAN 0x00020000
> +/**
> + * Mask of inner layer 2 packet types.
> + */
> +#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
> +/**
> + * IP (Internet Protocol) version 4 packet type.
> + * It is used for inner packet only, and does not contain any header option.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'ihl'=5>
> + */
> +#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
> +/**
> + * IP (Internet Protocol) version 4 packet type.
> + * It is used for inner packet only, and contains header options.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'ihl'=[6-15], 'options'>
> + */
> +#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
> +/**
> + * IP (Internet Protocol) version 6 packet type.
> + * It is used for inner packet only, and does not contain any extension header.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=0x3B>
> + */
> +#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
> +/**
> + * IP (Internet Protocol) version 4 packet type.
> + * It is used for inner packet only, and may or maynot contain header options.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'ihl'=[5-15], <'options'>>
> + */
> +#define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
> +/**
> + * IP (Internet Protocol) version 6 packet type.
> + * It is used for inner packet only, and contains extension headers.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> + * 'extension headers'>
> + */
> +#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
> +/**
> + * IP (Internet Protocol) version 6 packet type.
> + * It is used for inner packet only, and may or maynot contain extension
> + * headers.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
> + * <'extension headers'>>
> + */
> +#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
> +/**
> + * Mask of inner layer 3 packet types.
> + */
> +#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
> +/**
> + * TCP (Transmission Control Protocol) packet type.
> + * It is used for inner packet only.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=6, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=6>
> + */
> +#define RTE_PTYPE_INNER_L4_TCP 0x01000000
> +/**
> + * UDP (User Datagram Protocol) packet type.
> + * It is used for inner packet only.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=17, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=17>
> + */
> +#define RTE_PTYPE_INNER_L4_UDP 0x02000000
> +/**
> + * Fragmented IP (Internet Protocol) packet type.
> + * It is used for inner packet only, and may or maynot have layer 4 packet.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'MF'=1>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=44>
> + */
> +#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
> +/**
> + * SCTP (Stream Control Transmission Protocol) packet type.
> + * It is used for inner packet only.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=132, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=132>
> + */
> +#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
> +/**
> + * ICMP (Internet Control Message Protocol) packet type.
> + * It is used for inner packet only.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'=1, 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'=1>
> + */
> +#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
> +/**
> + * Non-fragmented IP (Internet Protocol) packet type.
> + * It is used for inner packet only, and may or maynot have other unknown layer
> + * 4 packet types.
> + *
> + * Packet format (inner only):
> + * <'ether type'=0x0800
> + * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
> + * or,
> + * <'ether type'=0x86DD
> + * | 'version'=6, 'next header'!=[6|17|44|132|1]>
> + */
> +#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
> +/**
> + * Mask of inner layer 4 packet types.
> + */
> +#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
> +
> +/**
> + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
> + * one, bit 4 is selected to be used for IPv4 only. Then checking bit 4 can
> + * determin if it is an IPV4 packet.
> + */
> +#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
> +
> +/**
> + * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
> + * one, bit 6 is selected to be used for IPv4 only. Then checking bit 6 can
> + * determin if it is an IPV4 packet.
> + */
> +#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
> +
> +/* Check if it is a tunneling packet */
> +#define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
> +#endif /* RTE_NEXT_ABI */
> +
> /**
> * Get the name of a RX offload flag
> *
>
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v2 08/11] hash: add new functionality to store data in hash table
@ 2015-06-30 7:36 3% ` Stephen Hemminger
0 siblings, 0 replies; 200+ results
From: Stephen Hemminger @ 2015-06-30 7:36 UTC (permalink / raw)
To: De Lara Guarch, Pablo; +Cc: dev
On Sun, 28 Jun 2015 22:23:28 +0000
"De Lara Guarch, Pablo" <pablo.de.lara.guarch@intel.com> wrote:
> Hi Stephen,
>
> > -----Original Message-----
> > From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> > Sent: Friday, June 26, 2015 5:50 PM
> > To: De Lara Guarch, Pablo
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v2 08/11] hash: add new functionality to
> > store data in hash table
> >
> > We did same thing with a slightly different method.
> >
> > Subject: rte_hash: split key and bucket size
> >
> > It is useful to store more data in the has bucket than just the key size.
> > For example, storing an addresss and additional data.
> >
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> Did you send this patch? I did not see it in the mailing list...
> Anyway, I like the idea of allowing the user to store variable size data (I was storing 8-byte data).
> So I have sent a v3 with a more similar method, although I still use the new functions,
> and use the parameter data_len for knowing the amount of bytes of data, and I keep constant the input key,
> and return the data in another parameter.
>
> Thanks for it!
> Pablo
I did not send the patch upstream because it would break the ABI and didn't
want to bother fighting that.
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v3 2/7] mbuf: use the reserved 16 bits for double vlan
2015-06-28 20:36 0% ` Thomas Monjalon
@ 2015-06-30 7:33 3% ` Olivier MATZ
0 siblings, 0 replies; 200+ results
From: Olivier MATZ @ 2015-06-30 7:33 UTC (permalink / raw)
To: Thomas Monjalon, Neil Horman; +Cc: dev
Hi,
On 06/28/2015 10:36 PM, Thomas Monjalon wrote:
> Neil, Olivier,
> Your opinions are requested here.
> Thanks
>
> 2015-06-25 08:31, Zhang, Helin:
>> Hi Neil
> [...]
>>> -279,7 +285,7 @@ struct rte_mbuf {
>>> uint16_t data_len; /**< Amount of data in segment buffer. */
>>> uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
>>> uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
>>> - uint16_t reserved;
>>> + uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU
>>> +order) */
>> Do you think here is a ABI break or not? Just using the reserved 16 bits, which was
>> intended for the second_vlan_tag. Thanks in advance!
>> I did not see any "Incompatible" reported by validate_abi.sh.
I don't feel there's any ABI break here. I think an application
should not use the "reserved" fields.
Regards,
Olivier
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCHv4 4/4] ABI: Add some documentation
2015-06-29 13:59 28% ` [dpdk-dev] [PATCHv4 4/4] ABI: Add some documentation Neil Horman
@ 2015-06-29 15:07 7% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-06-29 15:07 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-29 09:59, Neil Horman:
> People have been asking for ways to use the ABI macros, heres some docs to
> clarify their use. Included is:
>
> * An overview of what ABI is
> * Details of the ABI deprecation process
> * Details of the versioning macros
> * Examples of their use
> * Details of how to use the ABI validator
>
> Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
> working on it. Much of the introductory material was gathered and cleaned up by
> him
>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: john.mcnamara@intel.com
> CC: thomas.monjalon@6wind.com
>
> Change notes:
>
> v2)
> * Fixed RST indentations and spelling errors
> * Rebased to upstream to fix index.rst conflict
>
> v3)
> * Fixed in tact -> intact
> * Added docs to address static linking
> * Removed duplicate documentation from release notes
>
> v4)
> * Fixed more grammatical errors / etc
> * removed BASE_SYMBOL from documentation
Series applied with minor fixes, thanks
This doc should help to produce patches with new ABI without breaking
the old one.
For cases where the backward compatibility is impossible to achieve,
a patch amending this doc to suggest a NEXT_ABI option can be discussed.
^ permalink raw reply [relevance 7%]
* [dpdk-dev] [PATCHv4 4/4] ABI: Add some documentation
@ 2015-06-29 13:59 28% ` Neil Horman
2015-06-29 15:07 7% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-06-29 13:59 UTC (permalink / raw)
To: dev
People have been asking for ways to use the ABI macros, heres some docs to
clarify their use. Included is:
* An overview of what ABI is
* Details of the ABI deprecation process
* Details of the versioning macros
* Examples of their use
* Details of how to use the ABI validator
Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
working on it. Much of the introductory material was gathered and cleaned up by
him
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: john.mcnamara@intel.com
CC: thomas.monjalon@6wind.com
Change notes:
v2)
* Fixed RST indentations and spelling errors
* Rebased to upstream to fix index.rst conflict
v3)
* Fixed in tact -> intact
* Added docs to address static linking
* Removed duplicate documentation from release notes
v4)
* Fixed more grammatical errors / etc
* removed BASE_SYMBOL from documentation
---
doc/guides/guidelines/index.rst | 1 +
doc/guides/guidelines/versioning.rst | 480 +++++++++++++++++++++++++++++++++++
doc/guides/rel_notes/abi.rst | 30 +--
3 files changed, 483 insertions(+), 28 deletions(-)
create mode 100644 doc/guides/guidelines/versioning.rst
diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
index 0ee9ab3..bfb9fa3 100644
--- a/doc/guides/guidelines/index.rst
+++ b/doc/guides/guidelines/index.rst
@@ -7,3 +7,4 @@ Guidelines
coding_style
design
+ versioning
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
new file mode 100644
index 0000000..63526db
--- /dev/null
+++ b/doc/guides/guidelines/versioning.rst
@@ -0,0 +1,480 @@
+Managing ABI updates
+====================
+
+Description
+-----------
+
+This document details some methods for handling ABI management in the DPDK.
+Note this document is not exhaustive, in that C library versioning is flexible
+allowing multiple methods to achieve various goals, but it will provide the user
+with some introductory methods
+
+General Guidelines
+------------------
+
+#. Whenever possible, ABI should be preserved
+#. The addition of symbols is generally not problematic
+#. The modification of symbols can generally be managed with versioning
+#. The removal of symbols generally is an ABI break and requires bumping of the
+ LIBABIVER macro
+
+What is an ABI
+--------------
+
+An ABI (Application Binary Interface) is the set of runtime interfaces exposed
+by a library. It is similar to an API (Application Programming Interface) but
+is the result of compilation. It is also effectively cloned when applications
+link to dynamic libraries. That is to say when an application is compiled to
+link against dynamic libraries, it is assumed that the ABI remains constant
+between the time the application is compiled/linked, and the time that it runs.
+Therefore, in the case of dynamic linking, it is critical that an ABI is
+preserved, or (when modified), done in such a way that the application is unable
+to behave improperly or in an unexpected fashion.
+
+The DPDK ABI policy
+-------------------
+
+ABI versions are set at the time of major release labeling, and the ABI may
+change multiple times, without warning, between the last release label and the
+HEAD label of the git tree.
+
+ABI versions, once released, are available until such time as their
+deprecation has been noted in the Release Notes for at least one major release
+cycle. For example consider the case where the ABI for DPDK 2.0 has been
+shipped and then a decision is made to modify it during the development of
+DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1
+release and the modification will be made available in the DPDK 2.2 release.
+
+ABI versions may be deprecated in whole or in part as needed by a given
+update.
+
+Some ABI changes may be too significant to reasonably maintain multiple
+versions. In those cases ABI's may be updated without backward compatibility
+being provided. The requirements for doing so are:
+
+#. At least 3 acknowledgments of the need to do so must be made on the
+ dpdk.org mailing list.
+
+#. A full deprecation cycle, as explained above, must be made to offer
+ downstream consumers sufficient warning of the change.
+
+#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
+ incorporated must be incremented in parallel with the ABI changes
+ themselves.
+
+Note that the above process for ABI deprecation should not be undertaken
+lightly. ABI stability is extremely important for downstream consumers of the
+DPDK, especially when distributed in shared object form. Every effort should
+be made to preserve the ABI whenever possible. The ABI should only be changed
+for significant reasons, such as performance enhancements. ABI breakage due to
+changes such as reorganizing public structure fields for aesthetic or
+readability purposes should be avoided.
+
+Examples of Deprecation Notices
+-------------------------------
+
+The following are some examples of ABI deprecation notices which would be
+added to the Release Notes:
+
+* The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0,
+ to be replaced with the inline function ``rte_foo()``.
+
+* The function ``rte_mbuf_grok()`` has been updated to include a new parameter
+ in version 2.0. Backwards compatibility will be maintained for this function
+ until the release of version 2.1
+
+* The members of ``struct rte_foo`` have been reorganized in release 2.0 for
+ performance reasons. Existing binary applications will have backwards
+ compatibility in release 2.0, while newly built binaries will need to
+ reference the new structure variant ``struct rte_foo2``. Compatibility will
+ be removed in release 2.2, and all applications will require updating and
+ rebuilding to the new structure at that time, which will be renamed to the
+ original ``struct rte_foo``.
+
+* Significant ABI changes are planned for the ``librte_dostuff`` library. The
+ upcoming release 2.0 will not contain these changes, but release 2.1 will,
+ and no backwards compatibility is planned due to the extensive nature of
+ these changes. Binaries using this library built prior to version 2.1 will
+ require updating and recompilation.
+
+Versioning Macros
+-----------------
+
+When a symbol is exported from a library to provide an API, it also provides a
+calling convention (ABI) that is embodied in its name, return type and
+arguments. Occasionally that function may need to change to accommodate new
+functionality or behavior. When that occurs, it is desirable to allow for
+backward compatibility for a time with older binaries that are dynamically
+linked to the DPDK.
+
+To support backward compatibility the ``lib/librte_compat/rte_compat.h``
+header file provides macros to use when updating exported functions. These
+macros are used in conjunction with the ``rte_<library>_version.map`` file for
+a given library to allow multiple versions of a symbol to exist in a shared
+library so that older binaries need not be immediately recompiled.
+
+The macros exported are:
+
+* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
+ versioned symbol ``b@DPDK_n`` to the internal function ``b_e``.
+
+* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry instructing
+ the linker to bind references to symbol ``b`` to the internal symbol
+ ``b_e``.
+
+* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the fully
+qualified function ``p``, so that if a symbol becomes versioned, it can still be
+mapped back to the public symbol name.
+
+Examples of ABI Macro use
+-------------------------
+
+Updating a public API
+~~~~~~~~~~~~~~~~~~~~~
+
+Assume we have a function as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param)
+ {
+ ...
+ }
+
+
+Assume that struct rte_acl_ctx is a private structure, and that a developer
+wishes to enhance the acl api so that a debugging flag can be enabled on a
+per-context basis. This requires an addition to the structure (which, being
+private, is safe), but it also requires modifying the code as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param, int debug)
+ {
+ ...
+ }
+
+
+Note also that, being a public function, the header file prototype must also be
+changed, as must all the call sites, to reflect the new ABI footprint. We will
+maintain previous ABI versions that are accessible only to previously compiled
+binaries
+
+The addition of a parameter to the function is ABI breaking as the function is
+public, and existing application may use it in its current form. However, the
+compatibility macros in DPDK allow a developer to use symbol versioning so that
+multiple functions can be mapped to the same public symbol based on when an
+application was linked to it. To see how this is done, we start with the
+requisite libraries version map file. Initially the version map file for the
+acl library looks like this
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+This file needs to be modified as follows
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+
+ } DPDK_2.0;
+
+The addition of the new block tells the linker that a new version node is
+available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
+symbols from the DPDK_2.0 node. This list is directly translated into a list of
+exported symbols when DPDK is compiled as a shared library
+
+Next, we need to specify in the code which function map to the rte_acl_create
+symbol at which versions. First, at the site of the initial symbol definition,
+we need to update the function so that it is uniquely named, and not in conflict
+with the public symbol name
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param)
+ +rte_acl_create_v20(const struct rte_acl_param *param)
+ {
+ size_t sz;
+ struct rte_acl_ctx *ctx;
+ ...
+
+Note that the base name of the symbol was kept intact, as this is condusive to
+the macros used for versioning symbols. That is our next step, mapping this new
+symbol name to the initial symbol name at version node 2.0. Immediately after
+the function, we add this line of code
+
+.. code-block:: c
+
+ VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+Remembering to also add the rte_compat.h header to the requisite c file where
+these changes are being made. The above macro instructs the linker to create a
+new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
+builds, but now points to the above newly named function. We have now mapped
+the original rte_acl_create symbol to the original function (but with a new
+name)
+
+Next, we need to create the 2.1 version of the symbol. We create a new function
+name, with a different suffix, and implement it appropriately
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ rte_acl_create_v21(const struct rte_acl_param *param, int debug);
+ {
+ struct rte_acl_ctx *ctx = rte_acl_create_v20(param);
+
+ ctx->debug = debug;
+
+ return ctx;
+ }
+
+This code serves as our new API call. Its the same as our old call, but adds
+the new parameter in place. Next we need to map this function to the symbol
+``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call
+in the header file, adding the macro there to inform all including applications,
+that on re-link, the default rte_acl_create symbol should point to this
+function. Note that we could do this by simply naming the function above
+rte_acl_create, and the linker would chose the most recent version tag to apply
+in the version script, but we can also do this in the header file
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param);
+ +rte_acl_create(const struct rte_acl_param *param, int debug);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
+header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1
+version node to it. This method is more explicit and flexible than just
+re-implementing the exact symbol name, and allows for other features (such as
+linking to the old symbol version by default, when the new ABI is to be opt-in
+for a period.
+
+One last thing we need to do. Note that we've taken what was a public symbol,
+and duplicated it into two uniquely and differently named symbols. We've then
+mapped each of those back to the public symbol ``rte_acl_create`` with different
+version tags. This only applies to dynamic linking, as static linking has no
+notion of versioning. That leaves this code in a position of no longer having a
+symbol simply named ``rte_acl_create`` and a static build will fail on that
+missing symbol.
+
+To correct this, we can simply map a function of our choosing back to the public
+symbol in the static build with the ``MAP_STATIC_SYMBOL`` macro. Generally the
+assumption is that the most recent version of the symbol is the one you want to
+map. So, back in the C file where, immediately after ``rte_acl_create_v21`` is
+defined, we add this
+
+.. code-block:: c
+
+ struct rte_acl_create_v21(const struct rte_acl_param *param, int debug)
+ {
+ ...
+ }
+ MAP_STATIC_SYMBOL(struct rte_acl_create(const struct rte_acl_param *param, int debug), rte_acl_create_v21);
+
+That tells the compiler that, when building a static library, any calls to the
+symbol ``rte_acl_create`` should be linked to ``rte_acl_create_v21``
+
+That's it, on the next shared library rebuild, there will be two versions of
+rte_acl_create, an old DPDK_2.0 version, used by previously built applications,
+and a new DPDK_2.1 version, used by future built applications.
+
+
+Deprecating part of a public API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lets assume that you've done the above update, and after a few releases have
+passed you decide you would like to retire the old version of the function.
+After having gone through the ABI deprecation announcement process, removal is
+easy. Start by removing the symbol from the requisite version map file:
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ - rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+ } DPDK_2.0;
+
+
+Next remove the corresponding versioned export
+.. code-block:: c
+
+ -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+
+Note that the internal function definition could also be removed, but its used
+in our example by the newer version _v21, so we leave it in place. This is a
+coding style choice.
+
+Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
+indicate to applications doing dynamic linking that this is a later, and
+possibly incompatible library version:
+
+.. code-block:: c
+
+ -LIBABIVER := 1
+ +LIBABIVER := 2
+
+Deprecating an entire ABI version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+While removing a symbol from and ABI may be useful, it is often more practical
+to remove an entire version node at once. If a version node completely
+specifies an API, then removing part of it, typically makes it incomplete. In
+those cases it is better to remove the entire node
+
+To do this, start by modifying the version map file, such that all symbols from
+the node to be removed are merged into the next node in the map
+
+In the case of our map above, it would transform to look as follows
+
+.. code-block:: none
+
+ DPDK_2.1 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+Then any uses of BIND_DEFAULT_SYMBOL that pointed to the old node should be
+updated to point to the new version node in any header files for all affected
+symbols.
+
+.. code-block:: c
+
+ -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+Lastly, any VERSION_SYMBOL macros that point to the old version node should be
+removed, taking care to keep, where need old code in place to support newer
+versions of the symbol.
+
+Running the ABI Validator
+-------------------------
+
+The ``scripts`` directory in the DPDK source tree contains a utility program,
+``validate-abi.sh``, for validating the DPDK ABI based on the Linux `ABI
+Compliance Checker
+<http://ispras.linuxbase.org/index.php/ABI_compliance_checker>`_.
+
+This has a dependency on the ``abi-compliance-checker`` and ``and abi-dumper``
+utilities which can be installed via a package manager. For example::
+
+ sudo yum install abi-compliance-checker
+ sudo yum install abi-dumper
+
+The syntax of the ``validate-abi.sh`` utility is::
+
+ ./scripts/validate-abi.sh <TAG1> <TAG2> <TARGET>
+
+Where ``TAG1`` and ``TAG2`` are valid git tags on the local repo and target is
+the usual DPDK compilation target.
+
+For example to test the current committed HEAD against a previous release tag
+we could add a temporary tag and run the utility as follows::
+
+ git tag MY_TEMP_TAG
+ ./scripts/validate-abi.sh v2.0.0 MY_TEMP_TAG x86_64-native-linuxapp-gcc
+
+After the validation script completes (it can take a while since it need to
+compile both tags) it will create compatibility reports in the
+``./compat_report`` directory. Listed incompatibilities can be found as
+follows::
+
+ grep -lr Incompatible compat_reports/
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..4086198 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -1,33 +1,7 @@
ABI policy
==========
-ABI versions are set at the time of major release labeling, and ABI may change
-multiple times between the last labeling and the HEAD label of the git tree
-without warning.
-
-ABI versions, once released are available until such time as their
-deprecation has been noted here for at least one major release cycle, after it
-has been tagged. E.g. the ABI for DPDK 2.0 is shipped, and then the decision to
-remove it is made during the development of DPDK 2.1. The decision will be
-recorded here, shipped with the DPDK 2.1 release, and actually removed when DPDK
-2.2 ships.
-
-ABI versions may be deprecated in whole, or in part as needed by a given update.
-
-Some ABI changes may be too significant to reasonably maintain multiple
-versions of. In those events ABI's may be updated without backward
-compatibility provided. The requirements for doing so are:
-
-#. At least 3 acknowledgments of the need on the dpdk.org
-#. A full deprecation cycle must be made to offer downstream consumers sufficient warning of the change. E.g. if dpdk 2.0 is under development when the change is proposed, a deprecation notice must be added to this file, and released with dpdk 2.0. Then the change may be incorporated for dpdk 2.1
-#. The LIBABIVER variable in the makefile(s) where the ABI changes are incorporated must be incremented in parallel with the ABI changes themselves
-
-Note that the above process for ABI deprecation should not be undertaken
-lightly. ABI stability is extremely important for downstream consumers of the
-DPDK, especially when distributed in shared object form. Every effort should be
-made to preserve ABI whenever possible. For instance, reorganizing public
-structure field for aesthetic or readability purposes should be avoided as it will
-cause ABI breakage. Only significant (e.g. performance) reasons should be seen
-as cause to alter ABI.
+See the guidelines document for details of the ABI policy. ABI deprecation
+notices are to be posted here
Examples of Deprecation Notices
-------------------------------
--
2.1.0
^ permalink raw reply [relevance 28%]
* Re: [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation
2015-06-28 20:24 8% ` Thomas Monjalon
@ 2015-06-29 13:53 4% ` Neil Horman
0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2015-06-29 13:53 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Sun, Jun 28, 2015 at 10:24:42PM +0200, Thomas Monjalon wrote:
> 2015-06-26 10:54, Neil Horman:
> > On Fri, Jun 26, 2015 at 03:00:17PM +0200, Thomas Monjalon wrote:
> > > 2015-06-25 10:35, Neil Horman:
> > > > +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> > > > + unversioned symbol ``b`` to the internal function ``b_e``.
> > >
> > > Should a versioned symbol <b>@DPDK_<n>
> > >
> > Sure.
>
> When fixed, this series can be applied.
>
> > > > +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> > > > + unversioned symbol ``b`` to the internal function ``b_e``.
> > >
> > > Please give a use case of BASE_SYMBOL.
> > >
> > No, I'd rather remove it if you really insist. As noted before the way we set
> > up the version map files means we currently have no need for this particular
> > directive. I only included it for completeness. I think an example use in
> > light of that fact would only confuse people. If you're going to draw a line in
> > the sand around it, I'll just remove it.
>
> No line in the sand, but it seems better to remove it to avoid confusing people.
> ABI compat is already enough difficult to understand ;)
>
> > > [...]
> > > > +The addition of the new block tells the linker that a new version node is
> > > > +available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
> > > > +symbols from the DPDK_2.0 node.
> > >
> > > which contains the old version of the symbol rte_acl_create
> > >
> > I don't understand, is it not obvious that the DPDK_2.0 node contains the 2.0
> > version of the symbol and the DPDK_2.1 node contains the 2.1 version of the
> > symbol?
>
> Yes it is.
> I thought it was needed to insist on the existence of a new symbol while the
> old one still exists. Just trying to be didactic.
>
Ah, no its not a mandate (though doing so is an optional aproach, which trades
off the need to use MAP_STATIC_SYMBOL for the maintain a public symbol with the
same name). I can include an alternate example of the same exercize that
follows that approach, but given our time contraints would rather to that in a
follow up patch series
Neil
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCHv3 2/3] rte_compat: Add MAP_STATIC_SYMBOL macro
2015-06-28 20:13 0% ` Thomas Monjalon
@ 2015-06-29 13:44 0% ` Neil Horman
0 siblings, 0 replies; 200+ results
From: Neil Horman @ 2015-06-29 13:44 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Sun, Jun 28, 2015 at 10:13:31PM +0200, Thomas Monjalon wrote:
> 2015-06-26 10:30, Neil Horman:
> > On Fri, Jun 26, 2015 at 02:52:50PM +0200, Thomas Monjalon wrote:
> > > 2015-06-25 10:35, Neil Horman:
> > > > +/*
> > > > + * MAP_STATIC_SYMBOL
> > > > + * If a function has been bifurcated into multiple versions, none of which
> > > > + * are defined as the exported symbol name in the map file, this macro can be
> > > > + * used to alias a specific version of the symbol to its exported name. For
> > > > + * example, if you have 2 versions of a function foo_v1 and foo_v2, where the
> > > > + * former is mapped to foo@DPDK_1 and the latter is mapped to foo@DPDK_2 when
> > > > + * building a shared library, this macro can be used to map either foo_v1 or
> > > > + * foo_v2 to the symbol foo when building a static library, e.g.:
> > > > + * MAP_STATIC_SYMBOL(void foo(), foo_v2);
> > > > + */
> > > > +#define MAP_STATIC_SYMBOL(f, p)
> > > > +
> > > > #else
> > > > /*
> > > > * No symbol versioning in use
> > > > @@ -104,7 +105,7 @@
> > > > #define __vsym
> > > > #define BASE_SYMBOL(b, n)
> > > > #define BIND_DEFAULT_SYMBOL(b, e, n)
> > > > -
> > > > +#define MAP_STATIC_SYMBOL(f, p) f __attribute__((alias( RTE_STR(p))))
> > >
> > > Is it working with clang and icc?
> > No idea. It should work with clang (though I don't have it installed at the
> > moment), as the docs say the .symver directive is supported
> >
> > as for icc, thats out of my control completely, as I don't have any access to
> > it.
> >
> > > Why not just define foo as foo_v2?
> > I'm not sure what you mean here. Are you suggesting that we just change the abi
> > so applications have to call foo_v2 rather than foo when we change the
> > prototype. I suppose we could do that, but that seems like it would be an awful
> > irritant to users. They would rather have a single symbol to call if it does
> > the same function.
> >
> > > As this is the equivalent of BIND_DEFAULT_SYMBOL for the static case,
> > > it would be easier to mix them in only one macro.
> > >
> > Because of where its used. If you use BIND_DEFAULT_SYMBOL to do the work of
> > MAP_STATIC_SYMBOL, every compilation unit will define its own alias and you'll
> > get symbol conflicts.
>
> Oh, you mean it shouldn't be used in a .h file?
> If so, this limitation should be noted in the description above.
>
Its already noted in the example, I'd rather not make a unilateral statement
about where to use it above because there can be cause to use it internally as
well.
> OK for that solution, that's the best we have at the moment.
>
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH v2 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2
2015-06-29 13:42 4% [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping John McNamara
@ 2015-06-29 13:42 14% ` John McNamara
2015-07-02 1:24 0% ` [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping Lu, Wenzhuo
2015-07-02 15:16 4% ` [dpdk-dev] [PATCH v3 " John McNamara
2 siblings, 0 replies; 200+ results
From: John McNamara @ 2015-06-29 13:42 UTC (permalink / raw)
To: dev
Add announcement of a dedicated additional field in the mbuf
to support ieee1588 in DPDK 2.2.
Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
doc/guides/rel_notes/abi.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..51dacb2 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,8 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+
+* In DPDK 2.1 the IEEE1588/802.1AS support in the i40e driver makes use of the
+ ``udata64`` field in the mbuf to pass the timesync register index to the
+ user. In DPDK 2.2 this will be moved to a new field in the mbuf.
+
--
1.8.1.4
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping
@ 2015-06-29 13:42 4% John McNamara
2015-06-29 13:42 14% ` [dpdk-dev] [PATCH v2 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
` (2 more replies)
0 siblings, 3 replies; 200+ results
From: John McNamara @ 2015-06-29 13:42 UTC (permalink / raw)
To: dev
This patchset adds ethdev API to enable and read IEEE1588/802.1AS PTP
timestamps from devices that support it. The following functions are added:
rte_eth_timesync_enable()
rte_eth_timesync_disable()
rte_eth_timesync_read_rx_timestamp()
rte_eth_timesync_read_tx_timestamp()
The "ieee1588" forwarding mode in testpmd is also refactored to demonstrate
the new API and to clean up the code.
Adds support for igb, ixgbe and i40e.
V2:
* Added i40e support.
* Renamed ethdev functions from rte_eth_ieee15888_*() to rte_eth_timesync_*()
since 802.1AS can be supported through the same interfaces.
V1:
* Initial version for
John McNamara (7):
ethdev: add support for ieee1588 timestamping
e1000: add support for ieee1588 timestamping
ixgbe: add support for ieee1588 timestamping
i40e: add support for ieee1588 timestamping
app/testpmd: refactor ieee1588 forwarding
doc: document ieee1588 forwarding mode
abi: announce mbuf addition for ieee1588 in DPDK 2.2
app/test-pmd/ieee1588fwd.c | 466 ++--------------------------
doc/guides/rel_notes/abi.rst | 5 +
doc/guides/testpmd_app_ug/run_app.rst | 2 +-
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 2 +
drivers/net/e1000/igb_ethdev.c | 115 +++++++
drivers/net/i40e/i40e_ethdev.c | 143 +++++++++
drivers/net/i40e/i40e_rxtx.c | 39 ++-
drivers/net/ixgbe/ixgbe_ethdev.c | 122 ++++++++
lib/librte_ether/rte_ethdev.c | 70 ++++-
lib/librte_ether/rte_ethdev.h | 90 +++++-
lib/librte_ether/rte_ether_version.map | 4 +
11 files changed, 615 insertions(+), 443 deletions(-)
--
1.8.1.4
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v3 10/11] doc: announce ABI change of librte_hash
2015-06-28 22:25 4% ` [dpdk-dev] [PATCH v3 00/11] Cuckoo hash Pablo de Lara
@ 2015-06-28 22:25 14% ` Pablo de Lara
0 siblings, 0 replies; 200+ results
From: Pablo de Lara @ 2015-06-28 22:25 UTC (permalink / raw)
To: dev
rte_hash structure is now private for version 2.1, and two
of the macros in rte_hash.h are now deprecated, so this patch
adds notice of these changes.
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---
doc/guides/rel_notes/abi.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..fae09fd 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,5 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* Structure rte_hash in librte_hash library has been changed and has been made private in relese 2.1, as applications should have never accessed to its internal data (library should have been marked as internal).
+* The Macros #RTE_HASH_BUCKET_ENTRIES_MAX and #RTE_HASH_KEY_LENGTH_MAX are deprecated and will be removed with version 2.2.
--
2.4.2
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v3 00/11] Cuckoo hash
2015-06-25 22:05 4% ` [dpdk-dev] [PATCH v2 00/11] Cuckoo hash Pablo de Lara
2015-06-25 22:05 14% ` [dpdk-dev] [PATCH v2 10/11] doc: announce ABI change of librte_hash Pablo de Lara
@ 2015-06-28 22:25 4% ` Pablo de Lara
2015-06-28 22:25 14% ` [dpdk-dev] [PATCH v3 10/11] doc: announce ABI change of librte_hash Pablo de Lara
2 siblings, 1 reply; 200+ results
From: Pablo de Lara @ 2015-06-28 22:25 UTC (permalink / raw)
To: dev
This patchset is to replace the existing hash library with
a more efficient and functional approach, using the Cuckoo hash
method to deal with collisions. This method is based on using
two different hash functions to have two possible locations
in the hash table where an entry can be.
So, if a bucket is full, a new entry can push one of the items
in that bucket to its alternative location, making space for itself.
Advantages
~~~~~~
- Offers the option to store more entries when the target bucket is full
(unlike the previous implementation)
- Memory efficient: for storing those entries, it is not necessary to
request new memory, as the entries will be stored in the same table
- Constant worst lookup time: in worst case scenario, it always takes
the same time to look up an entry, as there are only two possible locations
where an entry can be.
- Storing data: user can store data in the hash table, unlike the
previous implementation, but he can still use the old API
This implementation tipically offers over 90% utilization.
Notice that API has been extended, but old API remains. The main
change in ABI is that rte_hash structure is now private and the
deprecation of two macros.
Changes in v3:
- Now user can store variable size data, instead of 32 or 64-bit size data,
using the new parameter "data_len" in rte_hash_parameters
- Add lookup_bulk_with_hash function in performance unit tests
- Add new functions that handle data in performance unit tests
- Remove duplicates in performance unit tests
- Fix rte_hash_reset, which was not reseting the last entry
Changes in v2:
- Fixed issue where table could not store maximum number of entries
- Fixed issue where lookup burst could not be more than 32 (instead of 64)
- Remove unnecessary macros and add other useful ones
- Added missing library dependencies
- Used directly rte_hash_secondary instead of rte_hash_alt
- Renamed rte_hash.c to rte_cuckoo_hash.c to ease the view of the new library
- Renamed test_hash_perf.c temporarily to ease the view of the improved unit test
- Moved rte_hash, rte_bucket and rte_hash_key structures to rte_cuckoo_hash.c to
make them private
- Corrected copyright dates
- Added an optimized function to compare keys that are multiple of 16 bytes
- Improved the way to use primary/secondary signatures. Now both are stored in
the bucket, so there is no need to calculate them if required.
Also, there is no need to use the MSB of a signature to differenciate between
an empty entry and signature 0, since we are storing both signatures,
which cannot be both 0.
- Removed rte_hash_rehash, as it was a very expensive operation.
Therefore, the add function returns now -ENOSPC if key cannot be added
because of a loop.
- Prefetched new slot for new key in add function to improve performance.
- Made doxygen comments more clear.
- Removed unnecessary rte_hash_del_key_data and rte_hash_del_key_with_data,
as we can use the lookup functions if we want to get the data before deleting.
- Removed some unnecessary includes in rte_hash.h
- Removed some unnecessary variables in rte_cuckoo_hash.c
- Removed some unnecessary checks before creating a new hash table
- Added documentation (in release notes and programmers guide)
- Added new unit tests and replaced the performance one for hash tables
Pablo de Lara (11):
eal: add const in prefetch functions
hash: move rte_hash structure to C file and make it internal
test/hash: enhance hash unit tests
test/hash: rename new hash perf unit test back to original name
hash: replace existing hash library with cuckoo hash implementation
hash: add new lookup_bulk_with_hash function
hash: add new function rte_hash_reset
hash: add new functionality to store data in hash table
MAINTAINERS: claim responsability for hash library
doc: announce ABI change of librte_hash
doc: update hash documentation
MAINTAINERS | 1 +
app/test/Makefile | 1 +
app/test/test_hash.c | 189 +--
app/test/test_hash_perf.c | 965 ++++++--------
doc/guides/prog_guide/hash_lib.rst | 77 +-
doc/guides/rel_notes/abi.rst | 2 +
.../common/include/arch/ppc_64/rte_prefetch.h | 6 +-
.../common/include/arch/x86/rte_prefetch.h | 14 +-
.../common/include/generic/rte_prefetch.h | 8 +-
lib/librte_hash/Makefile | 8 +-
lib/librte_hash/rte_cuckoo_hash.c | 1393 ++++++++++++++++++++
lib/librte_hash/rte_hash.c | 471 -------
lib/librte_hash/rte_hash.h | 275 +++-
lib/librte_hash/rte_hash_version.map | 15 +
14 files changed, 2250 insertions(+), 1175 deletions(-)
create mode 100644 lib/librte_hash/rte_cuckoo_hash.c
delete mode 100644 lib/librte_hash/rte_hash.c
--
2.4.2
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v3 2/7] mbuf: use the reserved 16 bits for double vlan
2015-06-25 8:31 3% ` Zhang, Helin
@ 2015-06-28 20:36 0% ` Thomas Monjalon
2015-06-30 7:33 3% ` Olivier MATZ
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-28 20:36 UTC (permalink / raw)
To: Neil Horman, olivier.matz; +Cc: dev
Neil, Olivier,
Your opinions are requested here.
Thanks
2015-06-25 08:31, Zhang, Helin:
> Hi Neil
[...]
> > -279,7 +285,7 @@ struct rte_mbuf {
> > uint16_t data_len; /**< Amount of data in segment buffer. */
> > uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
> > uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
> > - uint16_t reserved;
> > + uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU
> > +order) */
> Do you think here is a ABI break or not? Just using the reserved 16 bits, which was
> intended for the second_vlan_tag. Thanks in advance!
> I did not see any "Incompatible" reported by validate_abi.sh.
>
> Regards,
> Helin
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation
2015-06-26 14:54 4% ` Neil Horman
@ 2015-06-28 20:24 8% ` Thomas Monjalon
2015-06-29 13:53 4% ` Neil Horman
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-28 20:24 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-26 10:54, Neil Horman:
> On Fri, Jun 26, 2015 at 03:00:17PM +0200, Thomas Monjalon wrote:
> > 2015-06-25 10:35, Neil Horman:
> > > +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> > > + unversioned symbol ``b`` to the internal function ``b_e``.
> >
> > Should a versioned symbol <b>@DPDK_<n>
> >
> Sure.
When fixed, this series can be applied.
> > > +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> > > + unversioned symbol ``b`` to the internal function ``b_e``.
> >
> > Please give a use case of BASE_SYMBOL.
> >
> No, I'd rather remove it if you really insist. As noted before the way we set
> up the version map files means we currently have no need for this particular
> directive. I only included it for completeness. I think an example use in
> light of that fact would only confuse people. If you're going to draw a line in
> the sand around it, I'll just remove it.
No line in the sand, but it seems better to remove it to avoid confusing people.
ABI compat is already enough difficult to understand ;)
> > [...]
> > > +The addition of the new block tells the linker that a new version node is
> > > +available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
> > > +symbols from the DPDK_2.0 node.
> >
> > which contains the old version of the symbol rte_acl_create
> >
> I don't understand, is it not obvious that the DPDK_2.0 node contains the 2.0
> version of the symbol and the DPDK_2.1 node contains the 2.1 version of the
> symbol?
Yes it is.
I thought it was needed to insist on the existence of a new symbol while the
old one still exists. Just trying to be didactic.
Hope this documentation will help to unlock the patch series currently
breaking the ABI.
^ permalink raw reply [relevance 8%]
* Re: [dpdk-dev] [PATCHv3 2/3] rte_compat: Add MAP_STATIC_SYMBOL macro
2015-06-26 14:30 3% ` Neil Horman
@ 2015-06-28 20:13 0% ` Thomas Monjalon
2015-06-29 13:44 0% ` Neil Horman
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-28 20:13 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-26 10:30, Neil Horman:
> On Fri, Jun 26, 2015 at 02:52:50PM +0200, Thomas Monjalon wrote:
> > 2015-06-25 10:35, Neil Horman:
> > > +/*
> > > + * MAP_STATIC_SYMBOL
> > > + * If a function has been bifurcated into multiple versions, none of which
> > > + * are defined as the exported symbol name in the map file, this macro can be
> > > + * used to alias a specific version of the symbol to its exported name. For
> > > + * example, if you have 2 versions of a function foo_v1 and foo_v2, where the
> > > + * former is mapped to foo@DPDK_1 and the latter is mapped to foo@DPDK_2 when
> > > + * building a shared library, this macro can be used to map either foo_v1 or
> > > + * foo_v2 to the symbol foo when building a static library, e.g.:
> > > + * MAP_STATIC_SYMBOL(void foo(), foo_v2);
> > > + */
> > > +#define MAP_STATIC_SYMBOL(f, p)
> > > +
> > > #else
> > > /*
> > > * No symbol versioning in use
> > > @@ -104,7 +105,7 @@
> > > #define __vsym
> > > #define BASE_SYMBOL(b, n)
> > > #define BIND_DEFAULT_SYMBOL(b, e, n)
> > > -
> > > +#define MAP_STATIC_SYMBOL(f, p) f __attribute__((alias( RTE_STR(p))))
> >
> > Is it working with clang and icc?
> No idea. It should work with clang (though I don't have it installed at the
> moment), as the docs say the .symver directive is supported
>
> as for icc, thats out of my control completely, as I don't have any access to
> it.
>
> > Why not just define foo as foo_v2?
> I'm not sure what you mean here. Are you suggesting that we just change the abi
> so applications have to call foo_v2 rather than foo when we change the
> prototype. I suppose we could do that, but that seems like it would be an awful
> irritant to users. They would rather have a single symbol to call if it does
> the same function.
>
> > As this is the equivalent of BIND_DEFAULT_SYMBOL for the static case,
> > it would be easier to mix them in only one macro.
> >
> Because of where its used. If you use BIND_DEFAULT_SYMBOL to do the work of
> MAP_STATIC_SYMBOL, every compilation unit will define its own alias and you'll
> get symbol conflicts.
Oh, you mean it shouldn't be used in a .h file?
If so, this limitation should be noted in the description above.
OK for that solution, that's the best we have at the moment.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v6 0/9] Dynamic memzones
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
2015-06-26 15:29 1% ` [dpdk-dev] [PATCH v6 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-26 15:29 14% ` [dpdk-dev] [PATCH v6 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
@ 2015-06-26 16:13 0% ` Ananyev, Konstantin
2015-07-03 9:55 4% ` [dpdk-dev] [PATCH v7 " Sergio Gonzalez Monroy
3 siblings, 0 replies; 200+ results
From: Ananyev, Konstantin @ 2015-06-26 16:13 UTC (permalink / raw)
To: Gonzalez Monroy, Sergio, dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Sergio Gonzalez Monroy
> Sent: Friday, June 26, 2015 4:29 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v6 0/9] Dynamic memzones
>
> Current implemetation allows reserving/creating memzones but not the opposite
> (unreserve/free). This affects mempools and other memzone based objects.
>
> From my point of view, implementing free functionality for memzones would look
> like malloc over memsegs.
> Thus, this approach moves malloc inside eal (which in turn removes a circular
> dependency), where malloc heaps are composed of memsegs.
> We keep both malloc and memzone APIs as they are, but memzones allocate its
> memory by calling malloc_heap_alloc.
> Some extra functionality is required in malloc to allow for boundary constrained
> memory requests.
> In summary, currently malloc is based on memzones, and with this approach
> memzones are based on malloc.
>
> v6:
> - fix bad patch for rte_memzone_free
>
> v5:
> - Fix rte_memzone_free
> - Improve rte_memzone_free unit test
>
> v4:
> - Rebase and fix couple of merge issues
>
> v3:
> - Create dummy librte_malloc
> - Add deprecation notice
> - Rework some of the code
> - Doc update
> - checkpatch
>
> v2:
> - New rte_memzone_free
> - Support memzone len = 0
> - Add all available memsegs to malloc heap at init
> - Update memzone/malloc unit tests
>
> Sergio Gonzalez Monroy (9):
> eal: move librte_malloc to eal/common
> eal: memzone allocated by malloc
> app/test: update malloc/memzone unit tests
> config: remove CONFIG_RTE_MALLOC_MEMZONE_SIZE
> eal: remove free_memseg and references to it
> eal: new rte_memzone_free
> app/test: rte_memzone_free unit test
> doc: announce ABI change of librte_malloc
> doc: update malloc documentation
>
> MAINTAINERS | 9 +-
> app/test/test_malloc.c | 86 ----
> app/test/test_memzone.c | 456 ++++------------------
> config/common_bsdapp | 8 +-
> config/common_linuxapp | 8 +-
> doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++++++++-
> doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 80952 bytes
> doc/guides/prog_guide/index.rst | 1 -
> doc/guides/prog_guide/malloc_lib.rst | 233 -----------
> doc/guides/prog_guide/overview.rst | 11 +-
> doc/guides/rel_notes/abi.rst | 1 +
> drivers/net/af_packet/Makefile | 1 -
> drivers/net/bonding/Makefile | 1 -
> drivers/net/e1000/Makefile | 2 +-
> drivers/net/enic/Makefile | 2 +-
> drivers/net/fm10k/Makefile | 2 +-
> drivers/net/i40e/Makefile | 2 +-
> drivers/net/ixgbe/Makefile | 2 +-
> drivers/net/mlx4/Makefile | 1 -
> drivers/net/null/Makefile | 1 -
> drivers/net/pcap/Makefile | 1 -
> drivers/net/virtio/Makefile | 2 +-
> drivers/net/vmxnet3/Makefile | 2 +-
> drivers/net/xenvirt/Makefile | 2 +-
> lib/Makefile | 2 +-
> lib/librte_acl/Makefile | 2 +-
> lib/librte_eal/bsdapp/eal/Makefile | 4 +-
> lib/librte_eal/bsdapp/eal/rte_eal_version.map | 19 +
> lib/librte_eal/common/Makefile | 1 +
> lib/librte_eal/common/eal_common_memzone.c | 339 ++++++----------
> lib/librte_eal/common/include/rte_eal_memconfig.h | 5 +-
> lib/librte_eal/common/include/rte_malloc.h | 342 ++++++++++++++++
> lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
> lib/librte_eal/common/include/rte_memzone.h | 11 +
> lib/librte_eal/common/malloc_elem.c | 344 ++++++++++++++++
> lib/librte_eal/common/malloc_elem.h | 192 +++++++++
> lib/librte_eal/common/malloc_heap.c | 206 ++++++++++
> lib/librte_eal/common/malloc_heap.h | 70 ++++
> lib/librte_eal/common/rte_malloc.c | 259 ++++++++++++
> lib/librte_eal/linuxapp/eal/Makefile | 4 +-
> lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 +-
> lib/librte_eal/linuxapp/eal/rte_eal_version.map | 19 +
> lib/librte_hash/Makefile | 2 +-
> lib/librte_lpm/Makefile | 2 +-
> lib/librte_malloc/Makefile | 6 +-
> lib/librte_malloc/malloc_elem.c | 320 ---------------
> lib/librte_malloc/malloc_elem.h | 190 ---------
> lib/librte_malloc/malloc_heap.c | 208 ----------
> lib/librte_malloc/malloc_heap.h | 70 ----
> lib/librte_malloc/rte_malloc.c | 228 +----------
> lib/librte_malloc/rte_malloc.h | 342 ----------------
> lib/librte_malloc/rte_malloc_version.map | 16 -
> lib/librte_mempool/Makefile | 2 -
> lib/librte_port/Makefile | 1 -
> lib/librte_ring/Makefile | 3 +-
> lib/librte_table/Makefile | 1 -
> 56 files changed, 1928 insertions(+), 2356 deletions(-)
> delete mode 100644 doc/guides/prog_guide/malloc_lib.rst
> create mode 100644 lib/librte_eal/common/include/rte_malloc.h
> create mode 100644 lib/librte_eal/common/malloc_elem.c
> create mode 100644 lib/librte_eal/common/malloc_elem.h
> create mode 100644 lib/librte_eal/common/malloc_heap.c
> create mode 100644 lib/librte_eal/common/malloc_heap.h
> create mode 100644 lib/librte_eal/common/rte_malloc.c
> delete mode 100644 lib/librte_malloc/malloc_elem.c
> delete mode 100644 lib/librte_malloc/malloc_elem.h
> delete mode 100644 lib/librte_malloc/malloc_heap.c
> delete mode 100644 lib/librte_malloc/malloc_heap.h
> delete mode 100644 lib/librte_malloc/rte_malloc.h
>
> --
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 1.9.3
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH v6 2/9] eal: memzone allocated by malloc
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
@ 2015-06-26 15:29 1% ` Sergio Gonzalez Monroy
2015-06-26 15:29 14% ` [dpdk-dev] [PATCH v6 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
` (2 subsequent siblings)
3 siblings, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-26 15:29 UTC (permalink / raw)
To: dev
In the current memory hierarchy, memsegs are groups of physically
contiguous hugepages, memzones are slices of memsegs and malloc further
slices memzones into smaller memory chunks.
This patch modifies malloc so it partitions memsegs instead of memzones.
Thus memzones would call malloc internally for memory allocation while
maintaining its ABI.
It would be possible to free memzones and therefore any other structure
based on memzones, ie. mempools
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
lib/librte_eal/common/eal_common_memzone.c | 274 ++++++----------------
lib/librte_eal/common/include/rte_eal_memconfig.h | 2 +-
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/malloc_elem.c | 68 ++++--
lib/librte_eal/common/malloc_elem.h | 14 +-
lib/librte_eal/common/malloc_heap.c | 140 ++++++-----
lib/librte_eal/common/malloc_heap.h | 6 +-
lib/librte_eal/common/rte_malloc.c | 7 +-
8 files changed, 197 insertions(+), 317 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index aee184a..943012b 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -50,15 +50,15 @@
#include <rte_string_fns.h>
#include <rte_common.h>
+#include "malloc_heap.h"
+#include "malloc_elem.h"
#include "eal_private.h"
-/* internal copy of free memory segments */
-static struct rte_memseg *free_memseg = NULL;
-
static inline const struct rte_memzone *
memzone_lookup_thread_unsafe(const char *name)
{
const struct rte_mem_config *mcfg;
+ const struct rte_memzone *mz;
unsigned i = 0;
/* get pointer to global configuration */
@@ -68,8 +68,9 @@ memzone_lookup_thread_unsafe(const char *name)
* the algorithm is not optimal (linear), but there are few
* zones and this function should be called at init only
*/
- for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) {
- if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE))
+ for (i = 0; i < RTE_MAX_MEMZONE; i++) {
+ mz = &mcfg->memzone[i];
+ if (mz->addr != NULL && !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE))
return &mcfg->memzone[i];
}
@@ -88,39 +89,45 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id,
len, socket_id, flags, RTE_CACHE_LINE_SIZE);
}
-/*
- * Helper function for memzone_reserve_aligned_thread_unsafe().
- * Calculate address offset from the start of the segment.
- * Align offset in that way that it satisfy istart alignmnet and
- * buffer of the requested length would not cross specified boundary.
- */
-static inline phys_addr_t
-align_phys_boundary(const struct rte_memseg *ms, size_t len, size_t align,
- size_t bound)
+/* Find the heap with the greatest free block size */
+static void
+find_heap_max_free_elem(int *s, size_t *len, unsigned align)
{
- phys_addr_t addr_offset, bmask, end, start;
- size_t step;
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- step = RTE_MAX(align, bound);
- bmask = ~((phys_addr_t)bound - 1);
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate offset to closest alignment */
- start = RTE_ALIGN_CEIL(ms->phys_addr, align);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size > *len) {
+ *len = stats.greatest_free_size;
+ *s = i;
+ }
+ }
+ *len -= (MALLOC_ELEM_OVERHEAD + align);
+}
- while (addr_offset + len < ms->len) {
+/* Find a heap that can allocate the requested size */
+static void
+find_heap_suitable(int *s, size_t len, unsigned align)
+{
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- /* check, do we meet boundary condition */
- end = start + len - (len != 0);
- if ((start & bmask) == (end & bmask))
- break;
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate next offset */
- start = RTE_ALIGN_CEIL(start + 1, step);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size >= len + MALLOC_ELEM_OVERHEAD + align) {
+ *s = i;
+ break;
+ }
}
-
- return addr_offset;
}
static const struct rte_memzone *
@@ -128,13 +135,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
int socket_id, unsigned flags, unsigned align, unsigned bound)
{
struct rte_mem_config *mcfg;
- unsigned i = 0;
- int memseg_idx = -1;
- uint64_t addr_offset, seg_offset = 0;
size_t requested_len;
- size_t memseg_len = 0;
- phys_addr_t memseg_physaddr;
- void *memseg_addr;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
@@ -166,7 +167,6 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
if (align < RTE_CACHE_LINE_SIZE)
align = RTE_CACHE_LINE_SIZE;
-
/* align length on cache boundary. Check for overflow before doing so */
if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) {
rte_errno = EINVAL; /* requested size too big */
@@ -180,129 +180,50 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len);
/* check that boundary condition is valid */
- if (bound != 0 &&
- (requested_len > bound || !rte_is_power_of_2(bound))) {
+ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) {
rte_errno = EINVAL;
return NULL;
}
- /* find the smallest segment matching requirements */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- /* last segment */
- if (free_memseg[i].addr == NULL)
- break;
+ if (len == 0) {
+ if (bound != 0)
+ requested_len = bound;
+ else
+ requested_len = 0;
+ }
- /* empty segment, skip it */
- if (free_memseg[i].len == 0)
- continue;
-
- /* bad socket ID */
- if (socket_id != SOCKET_ID_ANY &&
- free_memseg[i].socket_id != SOCKET_ID_ANY &&
- socket_id != free_memseg[i].socket_id)
- continue;
-
- /*
- * calculate offset to closest alignment that
- * meets boundary conditions.
- */
- addr_offset = align_phys_boundary(free_memseg + i,
- requested_len, align, bound);
-
- /* check len */
- if ((requested_len + addr_offset) > free_memseg[i].len)
- continue;
-
- /* check flags for hugepage sizes */
- if ((flags & RTE_MEMZONE_2MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_1G)
- continue;
- if ((flags & RTE_MEMZONE_1GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_2M)
- continue;
- if ((flags & RTE_MEMZONE_16MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16G)
- continue;
- if ((flags & RTE_MEMZONE_16GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16M)
- continue;
-
- /* this segment is the best until now */
- if (memseg_idx == -1) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- /* find the biggest contiguous zone */
- else if (len == 0) {
- if (free_memseg[i].len > memseg_len) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- }
- /*
- * find the smallest (we already checked that current
- * zone length is > len
- */
- else if (free_memseg[i].len + align < memseg_len ||
- (free_memseg[i].len <= memseg_len + align &&
- addr_offset < seg_offset)) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
+ if (socket_id == SOCKET_ID_ANY) {
+ if (requested_len == 0)
+ find_heap_max_free_elem(&socket_id, &requested_len, align);
+ else
+ find_heap_suitable(&socket_id, requested_len, align);
+
+ if (socket_id == SOCKET_ID_ANY) {
+ rte_errno = ENOMEM;
+ return NULL;
}
}
- /* no segment found */
- if (memseg_idx == -1) {
- /*
- * If RTE_MEMZONE_SIZE_HINT_ONLY flag is specified,
- * try allocating again without the size parameter otherwise -fail.
- */
- if ((flags & RTE_MEMZONE_SIZE_HINT_ONLY) &&
- ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB)
- || (flags & RTE_MEMZONE_16MB) || (flags & RTE_MEMZONE_16GB)))
- return memzone_reserve_aligned_thread_unsafe(name,
- len, socket_id, 0, align, bound);
-
+ /* allocate memory on heap */
+ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket_id], NULL,
+ requested_len, flags, align, bound);
+ if (mz_addr == NULL) {
rte_errno = ENOMEM;
return NULL;
}
- /* save aligned physical and virtual addresses */
- memseg_physaddr = free_memseg[memseg_idx].phys_addr + seg_offset;
- memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr,
- (uintptr_t) seg_offset);
-
- /* if we are looking for a biggest memzone */
- if (len == 0) {
- if (bound == 0)
- requested_len = memseg_len - seg_offset;
- else
- requested_len = RTE_ALIGN_CEIL(memseg_physaddr + 1,
- bound) - memseg_physaddr;
- }
-
- /* set length to correct value */
- len = (size_t)seg_offset + requested_len;
-
- /* update our internal state */
- free_memseg[memseg_idx].len -= len;
- free_memseg[memseg_idx].phys_addr += len;
- free_memseg[memseg_idx].addr =
- (char *)free_memseg[memseg_idx].addr + len;
+ const struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
/* fill the zone in config */
struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++];
snprintf(mz->name, sizeof(mz->name), "%s", name);
- mz->phys_addr = memseg_physaddr;
- mz->addr = memseg_addr;
- mz->len = requested_len;
- mz->hugepage_sz = free_memseg[memseg_idx].hugepage_sz;
- mz->socket_id = free_memseg[memseg_idx].socket_id;
+ mz->phys_addr = rte_malloc_virt2phy(mz_addr);
+ mz->addr = mz_addr;
+ mz->len = (requested_len == 0 ? elem->size : requested_len);
+ mz->hugepage_sz = elem->ms->hugepage_sz;
+ mz->socket_id = elem->ms->socket_id;
mz->flags = 0;
- mz->memseg_id = memseg_idx;
+ mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg;
return mz;
}
@@ -419,45 +340,6 @@ rte_memzone_dump(FILE *f)
}
/*
- * called by init: modify the free memseg list to have cache-aligned
- * addresses and cache-aligned lengths
- */
-static int
-memseg_sanitize(struct rte_memseg *memseg)
-{
- unsigned phys_align;
- unsigned virt_align;
- unsigned off;
-
- phys_align = memseg->phys_addr & RTE_CACHE_LINE_MASK;
- virt_align = (unsigned long)memseg->addr & RTE_CACHE_LINE_MASK;
-
- /*
- * sanity check: phys_addr and addr must have the same
- * alignment
- */
- if (phys_align != virt_align)
- return -1;
-
- /* memseg is really too small, don't bother with it */
- if (memseg->len < (2 * RTE_CACHE_LINE_SIZE)) {
- memseg->len = 0;
- return 0;
- }
-
- /* align start address */
- off = (RTE_CACHE_LINE_SIZE - phys_align) & RTE_CACHE_LINE_MASK;
- memseg->phys_addr += off;
- memseg->addr = (char *)memseg->addr + off;
- memseg->len -= off;
-
- /* align end address */
- memseg->len &= ~((uint64_t)RTE_CACHE_LINE_MASK);
-
- return 0;
-}
-
-/*
* Init the memzone subsystem
*/
int
@@ -465,14 +347,10 @@ rte_eal_memzone_init(void)
{
struct rte_mem_config *mcfg;
const struct rte_memseg *memseg;
- unsigned i = 0;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
- /* mirror the runtime memsegs from config */
- free_memseg = mcfg->free_memseg;
-
/* secondary processes don't need to initialise anything */
if (rte_eal_process_type() == RTE_PROC_SECONDARY)
return 0;
@@ -485,33 +363,13 @@ rte_eal_memzone_init(void)
rte_rwlock_write_lock(&mcfg->mlock);
- /* fill in uninitialized free_memsegs */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (memseg[i].addr == NULL)
- break;
- if (free_memseg[i].addr != NULL)
- continue;
- memcpy(&free_memseg[i], &memseg[i], sizeof(struct rte_memseg));
- }
-
- /* make all zones cache-aligned */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (free_memseg[i].addr == NULL)
- break;
- if (memseg_sanitize(&free_memseg[i]) < 0) {
- RTE_LOG(ERR, EAL, "%s(): Sanity check failed\n", __func__);
- rte_rwlock_write_unlock(&mcfg->mlock);
- return -1;
- }
- }
-
/* delete all zones */
mcfg->memzone_idx = 0;
memset(mcfg->memzone, 0, sizeof(mcfg->memzone));
rte_rwlock_write_unlock(&mcfg->mlock);
- return 0;
+ return rte_eal_malloc_heap_init();
}
/* Walk all reserved memory zones */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 34f5abc..055212a 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -73,7 +73,7 @@ struct rte_mem_config {
struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */
struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */
- /* Runtime Physmem descriptors. */
+ /* Runtime Physmem descriptors - NOT USED */
struct rte_memseg free_memseg[RTE_MAX_MEMSEG];
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h
index 716216f..b270356 100644
--- a/lib/librte_eal/common/include/rte_malloc_heap.h
+++ b/lib/librte_eal/common/include/rte_malloc_heap.h
@@ -40,7 +40,7 @@
#include <rte_memory.h>
/* Number of free lists per heap, grouped by size. */
-#define RTE_HEAP_NUM_FREELISTS 5
+#define RTE_HEAP_NUM_FREELISTS 13
/**
* Structure to hold malloc heap
@@ -48,7 +48,6 @@
struct malloc_heap {
rte_spinlock_t lock;
LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS];
- unsigned mz_count;
unsigned alloc_count;
size_t total_size;
} __rte_cache_aligned;
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index a5e1248..b54ee33 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -37,7 +37,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include <rte_per_lcore.h>
@@ -56,10 +55,10 @@
*/
void
malloc_elem_init(struct malloc_elem *elem,
- struct malloc_heap *heap, const struct rte_memzone *mz, size_t size)
+ struct malloc_heap *heap, const struct rte_memseg *ms, size_t size)
{
elem->heap = heap;
- elem->mz = mz;
+ elem->ms = ms;
elem->prev = NULL;
memset(&elem->free_list, 0, sizeof(elem->free_list));
elem->state = ELEM_FREE;
@@ -70,12 +69,12 @@ malloc_elem_init(struct malloc_elem *elem,
}
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
{
- malloc_elem_init(elem, prev->heap, prev->mz, 0);
+ malloc_elem_init(elem, prev->heap, prev->ms, 0);
elem->prev = prev;
elem->state = ELEM_BUSY; /* mark busy so its never merged */
}
@@ -86,12 +85,24 @@ malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
* fit, return NULL.
*/
static void *
-elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
+elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- const uintptr_t end_pt = (uintptr_t)elem +
+ const size_t bmask = ~(bound - 1);
+ uintptr_t end_pt = (uintptr_t)elem +
elem->size - MALLOC_ELEM_TRAILER_LEN;
- const uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
- const uintptr_t new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
+ uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ uintptr_t new_elem_start;
+
+ /* check boundary */
+ if ((new_data_start & bmask) != ((end_pt - 1) & bmask)) {
+ end_pt = RTE_ALIGN_FLOOR(end_pt, bound);
+ new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ if (((end_pt - 1) & bmask) != (new_data_start & bmask))
+ return NULL;
+ }
+
+ new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
/* if the new start point is before the exist start, it won't fit */
return (new_elem_start < (uintptr_t)elem) ? NULL : (void *)new_elem_start;
@@ -102,9 +113,10 @@ elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
* alignment request from the current element
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- return elem_start_pt(elem, size, align) != NULL;
+ return elem_start_pt(elem, size, align, bound) != NULL;
}
/*
@@ -115,10 +127,10 @@ static void
split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)
{
struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size);
- const unsigned old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
- const unsigned new_elem_size = elem->size - old_elem_size;
+ const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
+ const size_t new_elem_size = elem->size - old_elem_size;
- malloc_elem_init(split_pt, elem->heap, elem->mz, new_elem_size);
+ malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size);
split_pt->prev = elem;
next_elem->prev = split_pt;
elem->size = old_elem_size;
@@ -168,8 +180,9 @@ malloc_elem_free_list_index(size_t size)
void
malloc_elem_free_list_insert(struct malloc_elem *elem)
{
- size_t idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
+ size_t idx;
+ idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
elem->state = ELEM_FREE;
LIST_INSERT_HEAD(&elem->heap->free_head[idx], elem, free_list);
}
@@ -190,12 +203,26 @@ elem_free_list_remove(struct malloc_elem *elem)
* is not done here, as it's done there previously.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- struct malloc_elem *new_elem = elem_start_pt(elem, size, align);
- const unsigned old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound);
+ const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ const size_t trailer_size = elem->size - old_elem_size - size -
+ MALLOC_ELEM_OVERHEAD;
+
+ elem_free_list_remove(elem);
- if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE){
+ if (trailer_size > MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* split it, too much free space after elem */
+ struct malloc_elem *new_free_elem =
+ RTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD);
+
+ split_elem(elem, new_free_elem);
+ malloc_elem_free_list_insert(new_free_elem);
+ }
+
+ if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
/* don't split it, pad the element instead */
elem->state = ELEM_BUSY;
elem->pad = old_elem_size;
@@ -208,8 +235,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
new_elem->size = elem->size - elem->pad;
set_header(new_elem);
}
- /* remove element from free list */
- elem_free_list_remove(elem);
return new_elem;
}
@@ -219,7 +244,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
* Re-insert original element, in case its new size makes it
* belong on a different list.
*/
- elem_free_list_remove(elem);
split_elem(elem, new_elem);
new_elem->state = ELEM_BUSY;
malloc_elem_free_list_insert(elem);
diff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h
index 9790b1a..e05d2ea 100644
--- a/lib/librte_eal/common/malloc_elem.h
+++ b/lib/librte_eal/common/malloc_elem.h
@@ -47,9 +47,9 @@ enum elem_state {
struct malloc_elem {
struct malloc_heap *heap;
- struct malloc_elem *volatile prev; /* points to prev elem in memzone */
+ struct malloc_elem *volatile prev; /* points to prev elem in memseg */
LIST_ENTRY(malloc_elem) free_list; /* list of free elements in heap */
- const struct rte_memzone *mz;
+ const struct rte_memseg *ms;
volatile enum elem_state state;
uint32_t pad;
size_t size;
@@ -136,11 +136,11 @@ malloc_elem_from_data(const void *data)
void
malloc_elem_init(struct malloc_elem *elem,
struct malloc_heap *heap,
- const struct rte_memzone *mz,
+ const struct rte_memseg *ms,
size_t size);
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem,
@@ -151,14 +151,16 @@ malloc_elem_mkend(struct malloc_elem *elem,
* of the requested size and with the requested alignment
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* reserve a block of data in an existing malloc_elem. If the malloc_elem
* is much larger than the data block requested, we split the element in two.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_alloc(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* free a malloc_elem block by adding it to the free list. If the
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 8861d27..f5fff96 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -39,7 +39,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_launch.h>
@@ -54,123 +53,104 @@
#include "malloc_elem.h"
#include "malloc_heap.h"
-/* since the memzone size starts with a digit, it will appear unquoted in
- * rte_config.h, so quote it so it can be passed to rte_str_to_size */
-#define MALLOC_MEMZONE_SIZE RTE_STR(RTE_MALLOC_MEMZONE_SIZE)
-
-/*
- * returns the configuration setting for the memzone size as a size_t value
- */
-static inline size_t
-get_malloc_memzone_size(void)
+static unsigned
+check_hugepage_sz(unsigned flags, size_t hugepage_sz)
{
- return rte_str_to_size(MALLOC_MEMZONE_SIZE);
+ unsigned ret = 1;
+
+ if ((flags & RTE_MEMZONE_2MB) && hugepage_sz == RTE_PGSIZE_1G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_1GB) && hugepage_sz == RTE_PGSIZE_2M)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16MB) && hugepage_sz == RTE_PGSIZE_16G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16GB) && hugepage_sz == RTE_PGSIZE_16M)
+ ret = 0;
+
+ return ret;
}
/*
- * reserve an extra memory zone and make it available for use by a particular
- * heap. This reserves the zone and sets a dummy malloc_elem header at the end
+ * Expand the heap with a memseg.
+ * This reserves the zone and sets a dummy malloc_elem header at the end
* to prevent overflow. The rest of the zone is added to free list as a single
* large free block
*/
-static int
-malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
+static void
+malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)
{
- const unsigned mz_flags = 0;
- const size_t block_size = get_malloc_memzone_size();
- /* ensure the data we want to allocate will fit in the memzone */
- const size_t min_size = size + align + MALLOC_ELEM_OVERHEAD * 2;
- const struct rte_memzone *mz = NULL;
- struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
- unsigned numa_socket = heap - mcfg->malloc_heaps;
-
- size_t mz_size = min_size;
- if (mz_size < block_size)
- mz_size = block_size;
-
- char mz_name[RTE_MEMZONE_NAMESIZE];
- snprintf(mz_name, sizeof(mz_name), "MALLOC_S%u_HEAP_%u",
- numa_socket, heap->mz_count++);
-
- /* try getting a block. if we fail and we don't need as big a block
- * as given in the config, we can shrink our request and try again
- */
- do {
- mz = rte_memzone_reserve(mz_name, mz_size, numa_socket,
- mz_flags);
- if (mz == NULL)
- mz_size /= 2;
- } while (mz == NULL && mz_size > min_size);
- if (mz == NULL)
- return -1;
-
/* allocate the memory block headers, one at end, one at start */
- struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
- struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
- mz_size - MALLOC_ELEM_OVERHEAD);
+ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr;
+ struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr,
+ ms->len - MALLOC_ELEM_OVERHEAD);
end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);
+ const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- malloc_elem_init(start_elem, heap, mz, elem_size);
+ malloc_elem_init(start_elem, heap, ms, elem_size);
malloc_elem_mkend(end_elem, start_elem);
malloc_elem_free_list_insert(start_elem);
- /* increase heap total size by size of new memzone */
- heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
- return 0;
+ heap->total_size += elem_size;
}
/*
* Iterates through the freelist for a heap to find a free element
* which can store data of the required size and with the requested alignment.
+ * If size is 0, find the biggest available elem.
* Returns null on failure, or pointer to element on success.
*/
static struct malloc_elem *
-find_suitable_element(struct malloc_heap *heap, size_t size, unsigned align)
+find_suitable_element(struct malloc_heap *heap, size_t size,
+ unsigned flags, size_t align, size_t bound)
{
size_t idx;
- struct malloc_elem *elem;
+ struct malloc_elem *elem, *alt_elem = NULL;
for (idx = malloc_elem_free_list_index(size);
- idx < RTE_HEAP_NUM_FREELISTS; idx++)
- {
+ idx < RTE_HEAP_NUM_FREELISTS; idx++) {
for (elem = LIST_FIRST(&heap->free_head[idx]);
- !!elem; elem = LIST_NEXT(elem, free_list))
- {
- if (malloc_elem_can_hold(elem, size, align))
- return elem;
+ !!elem; elem = LIST_NEXT(elem, free_list)) {
+ if (malloc_elem_can_hold(elem, size, align, bound)) {
+ if (check_hugepage_sz(flags, elem->ms->hugepage_sz))
+ return elem;
+ alt_elem = elem;
+ }
}
}
+
+ if ((alt_elem != NULL) && (flags & RTE_MEMZONE_SIZE_HINT_ONLY))
+ return alt_elem;
+
return NULL;
}
/*
- * Main function called by malloc to allocate a block of memory from the
- * heap. It locks the free list, scans it, and adds a new memzone if the
- * scan fails. Once the new memzone is added, it re-scans and should return
+ * Main function to allocate a block of memory from the heap.
+ * It locks the free list, scans it, and adds a new memseg if the
+ * scan fails. Once the new memseg is added, it re-scans and should return
* the new element after releasing the lock.
*/
void *
malloc_heap_alloc(struct malloc_heap *heap,
- const char *type __attribute__((unused)), size_t size, unsigned align)
+ const char *type __attribute__((unused)), size_t size, unsigned flags,
+ size_t align, size_t bound)
{
+ struct malloc_elem *elem;
+
size = RTE_CACHE_LINE_ROUNDUP(size);
align = RTE_CACHE_LINE_ROUNDUP(align);
+
rte_spinlock_lock(&heap->lock);
- struct malloc_elem *elem = find_suitable_element(heap, size, align);
- if (elem == NULL){
- if ((malloc_heap_add_memzone(heap, size, align)) == 0)
- elem = find_suitable_element(heap, size, align);
- }
- if (elem != NULL){
- elem = malloc_elem_alloc(elem, size, align);
+ elem = find_suitable_element(heap, size, flags, align, bound);
+ if (elem != NULL) {
+ elem = malloc_elem_alloc(elem, size, align, bound);
/* increase heap's count of allocated elements */
heap->alloc_count++;
}
rte_spinlock_unlock(&heap->lock);
- return elem == NULL ? NULL : (void *)(&elem[1]);
+ return elem == NULL ? NULL : (void *)(&elem[1]);
}
/*
@@ -206,3 +186,21 @@ malloc_heap_get_stats(const struct malloc_heap *heap,
socket_stats->alloc_count = heap->alloc_count;
return 0;
}
+
+int
+rte_eal_malloc_heap_init(void)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ unsigned ms_cnt;
+ struct rte_memseg *ms;
+
+ if (mcfg == NULL)
+ return -1;
+
+ for (ms = &mcfg->memseg[0], ms_cnt = 0;
+ (ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0);
+ ms_cnt++, ms++)
+ malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms);
+
+ return 0;
+}
diff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h
index a47136d..3ccbef0 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -53,15 +53,15 @@ malloc_get_numa_socket(void)
}
void *
-malloc_heap_alloc(struct malloc_heap *heap, const char *type,
- size_t size, unsigned align);
+malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size,
+ unsigned flags, size_t align, size_t bound);
int
malloc_heap_get_stats(const struct malloc_heap *heap,
struct rte_malloc_socket_stats *socket_stats);
int
-rte_eal_heap_memzone_init(void);
+rte_eal_malloc_heap_init(void);
#ifdef __cplusplus
}
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index c313a57..54c2bd8 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -39,7 +39,6 @@
#include <rte_memcpy.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_branch_prediction.h>
@@ -87,7 +86,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
return NULL;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL || socket_arg != SOCKET_ID_ANY)
return ret;
@@ -98,7 +97,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
continue;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL)
return ret;
}
@@ -256,5 +255,5 @@ rte_malloc_virt2phy(const void *addr)
const struct malloc_elem *elem = malloc_elem_from_data(addr);
if (elem == NULL)
return 0;
- return elem->mz->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->mz->addr);
+ return elem->ms->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->ms->addr);
}
--
1.9.3
^ permalink raw reply [relevance 1%]
* [dpdk-dev] [PATCH v6 0/9] Dynamic memzones
` (2 preceding siblings ...)
2015-06-26 11:32 4% ` [dpdk-dev] [PATCH v5 0/9] Dynamic memzones Sergio Gonzalez Monroy
@ 2015-06-26 15:29 4% ` Sergio Gonzalez Monroy
2015-06-26 15:29 1% ` [dpdk-dev] [PATCH v6 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
` (3 more replies)
3 siblings, 4 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-26 15:29 UTC (permalink / raw)
To: dev
Current implemetation allows reserving/creating memzones but not the opposite
(unreserve/free). This affects mempools and other memzone based objects.
>From my point of view, implementing free functionality for memzones would look
like malloc over memsegs.
Thus, this approach moves malloc inside eal (which in turn removes a circular
dependency), where malloc heaps are composed of memsegs.
We keep both malloc and memzone APIs as they are, but memzones allocate its
memory by calling malloc_heap_alloc.
Some extra functionality is required in malloc to allow for boundary constrained
memory requests.
In summary, currently malloc is based on memzones, and with this approach
memzones are based on malloc.
v6:
- fix bad patch for rte_memzone_free
v5:
- Fix rte_memzone_free
- Improve rte_memzone_free unit test
v4:
- Rebase and fix couple of merge issues
v3:
- Create dummy librte_malloc
- Add deprecation notice
- Rework some of the code
- Doc update
- checkpatch
v2:
- New rte_memzone_free
- Support memzone len = 0
- Add all available memsegs to malloc heap at init
- Update memzone/malloc unit tests
Sergio Gonzalez Monroy (9):
eal: move librte_malloc to eal/common
eal: memzone allocated by malloc
app/test: update malloc/memzone unit tests
config: remove CONFIG_RTE_MALLOC_MEMZONE_SIZE
eal: remove free_memseg and references to it
eal: new rte_memzone_free
app/test: rte_memzone_free unit test
doc: announce ABI change of librte_malloc
doc: update malloc documentation
MAINTAINERS | 9 +-
app/test/test_malloc.c | 86 ----
app/test/test_memzone.c | 456 ++++------------------
config/common_bsdapp | 8 +-
config/common_linuxapp | 8 +-
doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++++++++-
doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 80952 bytes
doc/guides/prog_guide/index.rst | 1 -
doc/guides/prog_guide/malloc_lib.rst | 233 -----------
doc/guides/prog_guide/overview.rst | 11 +-
doc/guides/rel_notes/abi.rst | 1 +
drivers/net/af_packet/Makefile | 1 -
drivers/net/bonding/Makefile | 1 -
drivers/net/e1000/Makefile | 2 +-
drivers/net/enic/Makefile | 2 +-
drivers/net/fm10k/Makefile | 2 +-
drivers/net/i40e/Makefile | 2 +-
drivers/net/ixgbe/Makefile | 2 +-
drivers/net/mlx4/Makefile | 1 -
drivers/net/null/Makefile | 1 -
drivers/net/pcap/Makefile | 1 -
drivers/net/virtio/Makefile | 2 +-
drivers/net/vmxnet3/Makefile | 2 +-
drivers/net/xenvirt/Makefile | 2 +-
lib/Makefile | 2 +-
lib/librte_acl/Makefile | 2 +-
lib/librte_eal/bsdapp/eal/Makefile | 4 +-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 19 +
lib/librte_eal/common/Makefile | 1 +
lib/librte_eal/common/eal_common_memzone.c | 339 ++++++----------
lib/librte_eal/common/include/rte_eal_memconfig.h | 5 +-
lib/librte_eal/common/include/rte_malloc.h | 342 ++++++++++++++++
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/include/rte_memzone.h | 11 +
lib/librte_eal/common/malloc_elem.c | 344 ++++++++++++++++
lib/librte_eal/common/malloc_elem.h | 192 +++++++++
lib/librte_eal/common/malloc_heap.c | 206 ++++++++++
lib/librte_eal/common/malloc_heap.h | 70 ++++
lib/librte_eal/common/rte_malloc.c | 259 ++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 4 +-
lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 +-
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 19 +
lib/librte_hash/Makefile | 2 +-
lib/librte_lpm/Makefile | 2 +-
lib/librte_malloc/Makefile | 6 +-
lib/librte_malloc/malloc_elem.c | 320 ---------------
lib/librte_malloc/malloc_elem.h | 190 ---------
lib/librte_malloc/malloc_heap.c | 208 ----------
lib/librte_malloc/malloc_heap.h | 70 ----
lib/librte_malloc/rte_malloc.c | 228 +----------
lib/librte_malloc/rte_malloc.h | 342 ----------------
lib/librte_malloc/rte_malloc_version.map | 16 -
lib/librte_mempool/Makefile | 2 -
lib/librte_port/Makefile | 1 -
lib/librte_ring/Makefile | 3 +-
lib/librte_table/Makefile | 1 -
56 files changed, 1928 insertions(+), 2356 deletions(-)
delete mode 100644 doc/guides/prog_guide/malloc_lib.rst
create mode 100644 lib/librte_eal/common/include/rte_malloc.h
create mode 100644 lib/librte_eal/common/malloc_elem.c
create mode 100644 lib/librte_eal/common/malloc_elem.h
create mode 100644 lib/librte_eal/common/malloc_heap.c
create mode 100644 lib/librte_eal/common/malloc_heap.h
create mode 100644 lib/librte_eal/common/rte_malloc.c
delete mode 100644 lib/librte_malloc/malloc_elem.c
delete mode 100644 lib/librte_malloc/malloc_elem.h
delete mode 100644 lib/librte_malloc/malloc_heap.c
delete mode 100644 lib/librte_malloc/malloc_heap.h
delete mode 100644 lib/librte_malloc/rte_malloc.h
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v6 8/9] doc: announce ABI change of librte_malloc
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
2015-06-26 15:29 1% ` [dpdk-dev] [PATCH v6 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
@ 2015-06-26 15:29 14% ` Sergio Gonzalez Monroy
2015-06-26 16:13 0% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Ananyev, Konstantin
2015-07-03 9:55 4% ` [dpdk-dev] [PATCH v7 " Sergio Gonzalez Monroy
3 siblings, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-26 15:29 UTC (permalink / raw)
To: dev
Announce the creation of dummy malloc library for 2.1 and removal of
such library, now integrated in librte_eal, for 2.2 release.
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
doc/guides/rel_notes/abi.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..2aaf900 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,4 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* librte_malloc library has been integrated into librte_eal. The 2.1 release creates a dummy/empty malloc library to fulfill binaries with dynamic linking dependencies on librte_malloc.so. Such dummy library will not be created from release 2.2 so binaries will need to be rebuilt.
--
1.9.3
^ permalink raw reply [relevance 14%]
* Re: [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation
2015-06-26 13:00 4% ` Thomas Monjalon
@ 2015-06-26 14:54 4% ` Neil Horman
2015-06-28 20:24 8% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-06-26 14:54 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Fri, Jun 26, 2015 at 03:00:17PM +0200, Thomas Monjalon wrote:
> 2015-06-25 10:35, Neil Horman:
> > v3)
> > * Fixed in tact -> intact
> > * Added docs to address static linking
> > * Removed duplicate documentation from release notes
>
> It seems you missed some of my previous comments.
>
> [...]
> > +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> > + unversioned symbol ``b`` to the internal function ``b_e``.
>
> Should a versioned symbol <b>@DPDK_<n>
>
Sure.
> > +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> > + unversioned symbol ``b`` to the internal function ``b_e``.
>
> Please give a use case of BASE_SYMBOL.
>
No, I'd rather remove it if you really insist. As noted before the way we set
up the version map files means we currently have no need for this particular
directive. I only included it for completeness. I think an example use in
light of that fact would only confuse people. If you're going to draw a line in
the sand around it, I'll just remove it.
> [...]
> > +The addition of the new block tells the linker that a new version node is
> > +available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
> > +symbols from the DPDK_2.0 node.
>
> which contains the old version of the symbol rte_acl_create
>
I don't understand, is it not obvious that the DPDK_2.0 node contains the 2.0
version of the symbol and the DPDK_2.1 node contains the 2.1 version of the
symbol?
Neil
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs
2015-06-26 14:30 11% ` Tahhan, Maryam
@ 2015-06-26 14:37 0% ` Kyle Larose
0 siblings, 0 replies; 200+ results
From: Kyle Larose @ 2015-06-26 14:37 UTC (permalink / raw)
To: Tahhan, Maryam; +Cc: dev
Hi Maryam,
I was not aware of the proc_info app. Is there any documentation on dpdk.org
about it, or should I browse the code?
Thanks,
Kyle
On Fri, Jun 26, 2015 at 10:30 AM, Tahhan, Maryam <maryam.tahhan@intel.com>
wrote:
>
>
> On Fri, Jun 26, 2015 at 8:59 AM, Maryam Tahhan <maryam.tahhan@intel.com>
> wrote:
>
> Remove non generic stats in rte_stats_strings and mark the relevant
> fields in struct rte_eth_stats as deprecated.
>
> Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
> ---
> doc/guides/rel_notes/abi.rst | 11 +++++++++++
> lib/librte_ether/rte_ethdev.c | 9 ---------
> lib/librte_ether/rte_ethdev.h | 30 ++++++++++++++++++++----------
> 3 files changed, 31 insertions(+), 19 deletions(-)
>
> diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
> index f00a6ee..957b13f 100644
> --- a/doc/guides/rel_notes/abi.rst
> +++ b/doc/guides/rel_notes/abi.rst
> @@ -38,3 +38,14 @@ Examples of Deprecation Notices
>
> Deprecation Notices
> -------------------
> +* The following fields have been deprecated in rte_eth_stats:
> + * uint64_t imissed
> + * uint64_t ibadcrc
> + * uint64_t ibadlen
> + * uint64_t imcasts
> + * uint64_t fdirmatch
> + * uint64_t fdirmiss
> + * uint64_t tx_pause_xon
> + * uint64_t rx_pause_xon
> + * uint64_t tx_pause_xoff
> + * uint64_t rx_pause_xoff
>
>
>
> Are CRC errors (ibadcrc) truly hardware specific? Which NIC (aside from
> purely virtual ones) does not have a MAC which does frame checksumming?
> Likewise, which NIC doesn't drop because the PCI bus/cpu/etc is too busy to
> pull packets off of it (imissed)?
>
> Debugging interactions with NICs is hard enough with only CRC errors and
> missed packets to go on. Without those it is close to impossible. CRC
> errors are almost guaranteed any time a bare-metal application is deployed:
> dirty fiber, bad SFPs, etc. How will users of the application be able to
> determine why their packets are dropping if they can only see "in errors"?
>
> I understand that we want to avoid placing too much useless information
> into these statistics structures. However, without a hardware-independent
> way of accessing fairly standard networking-equipment diagnostics, I feel
> like any real-world application using DPDK will be terribly cumbersome to
> build: every single one will need to develop an abstraction layer which
> detects the attached NICs, and loads an appropriate driver to integrate
> with the xstats api.
>
>
>
> Is there any plan for such an API? If not, is it really a good idea to
> deprecate these stats?
>
> Thanks,
>
> Kyle
>
>
>
> Hi Kyle
>
>
>
> If it’s just for debug/diagnostic purposes that this information is being
> used then I would recommend using the proc_info app which is already
> integrated with xstats will give you detailed error statistics. It runs as
> a DPDK secondary process.
>
>
>
> I’m not sure about crcerrors and imissed, I had taken feedback to my
> previous version of the patches onboard and made the changes based on that.
>
>
>
> Regards
>
> Maryam
>
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCHv3 2/3] rte_compat: Add MAP_STATIC_SYMBOL macro
@ 2015-06-26 14:30 3% ` Neil Horman
2015-06-28 20:13 0% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-06-26 14:30 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Fri, Jun 26, 2015 at 02:52:50PM +0200, Thomas Monjalon wrote:
> 2015-06-25 10:35, Neil Horman:
> > +/*
> > + * MAP_STATIC_SYMBOL
> > + * If a function has been bifurcated into multiple versions, none of which
> > + * are defined as the exported symbol name in the map file, this macro can be
> > + * used to alias a specific version of the symbol to its exported name. For
> > + * example, if you have 2 versions of a function foo_v1 and foo_v2, where the
> > + * former is mapped to foo@DPDK_1 and the latter is mapped to foo@DPDK_2 when
> > + * building a shared library, this macro can be used to map either foo_v1 or
> > + * foo_v2 to the symbol foo when building a static library, e.g.:
> > + * MAP_STATIC_SYMBOL(void foo(), foo_v2);
> > + */
> > +#define MAP_STATIC_SYMBOL(f, p)
> > +
> > #else
> > /*
> > * No symbol versioning in use
> > @@ -104,7 +105,7 @@
> > #define __vsym
> > #define BASE_SYMBOL(b, n)
> > #define BIND_DEFAULT_SYMBOL(b, e, n)
> > -
> > +#define MAP_STATIC_SYMBOL(f, p) f __attribute__((alias( RTE_STR(p))))
>
> Is it working with clang and icc?
No idea. It should work with clang (though I don't have it installed at the
moment), as the docs say the .symver directive is supported
as for icc, thats out of my control completely, as I don't have any access to
it.
> Why not just define foo as foo_v2?
I'm not sure what you mean here. Are you suggesting that we just change the abi
so applications have to call foo_v2 rather than foo when we change the
prototype. I suppose we could do that, but that seems like it would be an awful
irritant to users. They would rather have a single symbol to call if it does
the same function.
> As this is the equivalent of BIND_DEFAULT_SYMBOL for the static case,
> it would be easier to mix them in only one macro.
>
Because of where its used. If you use BIND_DEFAULT_SYMBOL to do the work of
MAP_STATIC_SYMBOL, every compilation unit will define its own alias and you'll
get symbol conflicts.
Neil
>
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs
2015-06-26 14:03 0% ` Kyle Larose
@ 2015-06-26 14:30 11% ` Tahhan, Maryam
2015-06-26 14:37 0% ` Kyle Larose
0 siblings, 1 reply; 200+ results
From: Tahhan, Maryam @ 2015-06-26 14:30 UTC (permalink / raw)
To: Kyle Larose; +Cc: dev
On Fri, Jun 26, 2015 at 8:59 AM, Maryam Tahhan <maryam.tahhan@intel.com<mailto:maryam.tahhan@intel.com>> wrote:
Remove non generic stats in rte_stats_strings and mark the relevant
fields in struct rte_eth_stats as deprecated.
Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com<mailto:maryam.tahhan@intel.com>>
---
doc/guides/rel_notes/abi.rst | 11 +++++++++++
lib/librte_ether/rte_ethdev.c | 9 ---------
lib/librte_ether/rte_ethdev.h | 30 ++++++++++++++++++++----------
3 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..957b13f 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,14 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* The following fields have been deprecated in rte_eth_stats:
+ * uint64_t imissed
+ * uint64_t ibadcrc
+ * uint64_t ibadlen
+ * uint64_t imcasts
+ * uint64_t fdirmatch
+ * uint64_t fdirmiss
+ * uint64_t tx_pause_xon
+ * uint64_t rx_pause_xon
+ * uint64_t tx_pause_xoff
+ * uint64_t rx_pause_xoff
Are CRC errors (ibadcrc) truly hardware specific? Which NIC (aside from purely virtual ones) does not have a MAC which does frame checksumming? Likewise, which NIC doesn't drop because the PCI bus/cpu/etc is too busy to pull packets off of it (imissed)?
Debugging interactions with NICs is hard enough with only CRC errors and missed packets to go on. Without those it is close to impossible. CRC errors are almost guaranteed any time a bare-metal application is deployed: dirty fiber, bad SFPs, etc. How will users of the application be able to determine why their packets are dropping if they can only see "in errors"?
I understand that we want to avoid placing too much useless information into these statistics structures. However, without a hardware-independent way of accessing fairly standard networking-equipment diagnostics, I feel like any real-world application using DPDK will be terribly cumbersome to build: every single one will need to develop an abstraction layer which detects the attached NICs, and loads an appropriate driver to integrate with the xstats api.
Is there any plan for such an API? If not, is it really a good idea to deprecate these stats?
Thanks,
Kyle
Hi Kyle
If it’s just for debug/diagnostic purposes that this information is being used then I would recommend using the proc_info app which is already integrated with xstats will give you detailed error statistics. It runs as a DPDK secondary process.
I’m not sure about crcerrors and imissed, I had taken feedback to my previous version of the patches onboard and made the changes based on that.
Regards
Maryam
^ permalink raw reply [relevance 11%]
* Re: [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs
2015-06-26 12:59 9% ` [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs Maryam Tahhan
@ 2015-06-26 14:03 0% ` Kyle Larose
2015-06-26 14:30 11% ` Tahhan, Maryam
0 siblings, 1 reply; 200+ results
From: Kyle Larose @ 2015-06-26 14:03 UTC (permalink / raw)
To: Maryam Tahhan; +Cc: dev
On Fri, Jun 26, 2015 at 8:59 AM, Maryam Tahhan <maryam.tahhan@intel.com>
wrote:
> Remove non generic stats in rte_stats_strings and mark the relevant
> fields in struct rte_eth_stats as deprecated.
>
> Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
> ---
> doc/guides/rel_notes/abi.rst | 11 +++++++++++
> lib/librte_ether/rte_ethdev.c | 9 ---------
> lib/librte_ether/rte_ethdev.h | 30 ++++++++++++++++++++----------
> 3 files changed, 31 insertions(+), 19 deletions(-)
>
> diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
> index f00a6ee..957b13f 100644
> --- a/doc/guides/rel_notes/abi.rst
> +++ b/doc/guides/rel_notes/abi.rst
> @@ -38,3 +38,14 @@ Examples of Deprecation Notices
>
> Deprecation Notices
> -------------------
> +* The following fields have been deprecated in rte_eth_stats:
> + * uint64_t imissed
> + * uint64_t ibadcrc
> + * uint64_t ibadlen
> + * uint64_t imcasts
> + * uint64_t fdirmatch
> + * uint64_t fdirmiss
> + * uint64_t tx_pause_xon
> + * uint64_t rx_pause_xon
> + * uint64_t tx_pause_xoff
> + * uint64_t rx_pause_xoff
>
>
Are CRC errors (ibadcrc) truly hardware specific? Which NIC (aside from
purely virtual ones) does not have a MAC which does frame checksumming?
Likewise, which NIC doesn't drop because the PCI bus/cpu/etc is too busy to
pull packets off of it (imissed)?
Debugging interactions with NICs is hard enough with only CRC errors and
missed packets to go on. Without those it is close to impossible. CRC
errors are almost guaranteed any time a bare-metal application is deployed:
dirty fiber, bad SFPs, etc. How will users of the application be able to
determine why their packets are dropping if they can only see "in errors"?
I understand that we want to avoid placing too much useless information
into these statistics structures. However, without a hardware-independent
way of accessing fairly standard networking-equipment diagnostics, I feel
like any real-world application using DPDK will be terribly cumbersome to
build: every single one will need to develop an abstraction layer which
detects the attached NICs, and loads an appropriate driver to integrate
with the xstats api.
Is there any plan for such an API? If not, is it really a good idea to
deprecate these stats?
Thanks,
Kyle
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation
2015-06-25 14:35 28% ` [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation Neil Horman
@ 2015-06-26 13:00 4% ` Thomas Monjalon
2015-06-26 14:54 4% ` Neil Horman
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-26 13:00 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-25 10:35, Neil Horman:
> v3)
> * Fixed in tact -> intact
> * Added docs to address static linking
> * Removed duplicate documentation from release notes
It seems you missed some of my previous comments.
[...]
> +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> + unversioned symbol ``b`` to the internal function ``b_e``.
Should a versioned symbol <b>@DPDK_<n>
> +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> + unversioned symbol ``b`` to the internal function ``b_e``.
Please give a use case of BASE_SYMBOL.
[...]
> +The addition of the new block tells the linker that a new version node is
> +available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
> +symbols from the DPDK_2.0 node.
which contains the old version of the symbol rte_acl_create
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs
2015-06-26 12:59 3% [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps Maryam Tahhan
@ 2015-06-26 12:59 9% ` Maryam Tahhan
2015-06-26 14:03 0% ` Kyle Larose
2015-07-01 14:27 0% ` [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps Tahhan, Maryam
1 sibling, 1 reply; 200+ results
From: Maryam Tahhan @ 2015-06-26 12:59 UTC (permalink / raw)
To: dev
Remove non generic stats in rte_stats_strings and mark the relevant
fields in struct rte_eth_stats as deprecated.
Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
---
doc/guides/rel_notes/abi.rst | 11 +++++++++++
lib/librte_ether/rte_ethdev.c | 9 ---------
lib/librte_ether/rte_ethdev.h | 30 ++++++++++++++++++++----------
3 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..957b13f 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,14 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* The following fields have been deprecated in rte_eth_stats:
+ * uint64_t imissed
+ * uint64_t ibadcrc
+ * uint64_t ibadlen
+ * uint64_t imcasts
+ * uint64_t fdirmatch
+ * uint64_t fdirmiss
+ * uint64_t tx_pause_xon
+ * uint64_t rx_pause_xon
+ * uint64_t tx_pause_xoff
+ * uint64_t rx_pause_xoff
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 6451621..8176baf 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -125,17 +125,8 @@ static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
{"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
{"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
{"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
- {"rx_missed_errors", offsetof(struct rte_eth_stats, imissed)},
- {"rx_crc_errors", offsetof(struct rte_eth_stats, ibadcrc)},
- {"rx_bad_length_errors", offsetof(struct rte_eth_stats, ibadlen)},
{"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
{"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
- {"fdir_match", offsetof(struct rte_eth_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct rte_eth_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct rte_eth_stats, tx_pause_xon)},
- {"rx_flow_control_xon", offsetof(struct rte_eth_stats, rx_pause_xon)},
- {"tx_flow_control_xoff", offsetof(struct rte_eth_stats, tx_pause_xoff)},
- {"rx_flow_control_xoff", offsetof(struct rte_eth_stats, rx_pause_xoff)},
};
#define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index f1219ac..a38d49a 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -193,19 +193,29 @@ struct rte_eth_stats {
uint64_t opackets; /**< Total number of successfully transmitted packets.*/
uint64_t ibytes; /**< Total number of successfully received bytes. */
uint64_t obytes; /**< Total number of successfully transmitted bytes. */
- uint64_t imissed; /**< Total of RX missed packets (e.g full FIFO). */
- uint64_t ibadcrc; /**< Total of RX packets with CRC error. */
- uint64_t ibadlen; /**< Total of RX packets with bad length. */
+ /**< Deprecated; Total of RX missed packets (e.g full FIFO). */
+ uint64_t imissed;
+ /**< Deprecated; Total of RX packets with CRC error. */
+ uint64_t ibadcrc;
+ /**< Deprecated; Total of RX packets with bad length. */
+ uint64_t ibadlen;
uint64_t ierrors; /**< Total number of erroneous received packets. */
uint64_t oerrors; /**< Total number of failed transmitted packets. */
- uint64_t imcasts; /**< Total number of multicast received packets. */
+ uint64_t imcasts;
+ /**< Deprecated; Total number of multicast received packets. */
uint64_t rx_nombuf; /**< Total number of RX mbuf allocation failures. */
- uint64_t fdirmatch; /**< Total number of RX packets matching a filter. */
- uint64_t fdirmiss; /**< Total number of RX packets not matching any filter. */
- uint64_t tx_pause_xon; /**< Total nb. of XON pause frame sent. */
- uint64_t rx_pause_xon; /**< Total nb. of XON pause frame received. */
- uint64_t tx_pause_xoff; /**< Total nb. of XOFF pause frame sent. */
- uint64_t rx_pause_xoff; /**< Total nb. of XOFF pause frame received. */
+ uint64_t fdirmatch;
+ /**< Deprecated; Total number of RX packets matching a filter. */
+ uint64_t fdirmiss;
+ /**< Deprecated; Total number of RX packets not matching any filter. */
+ uint64_t tx_pause_xon;
+ /**< Deprecated; Total nb. of XON pause frame sent. */
+ uint64_t rx_pause_xon;
+ /**< Deprecated; Total nb. of XON pause frame received. */
+ uint64_t tx_pause_xoff;
+ /**< Deprecated; Total nb. of XOFF pause frame sent. */
+ uint64_t rx_pause_xoff;
+ /**< Deprecated; Total nb. of XOFF pause frame received. */
uint64_t q_ipackets[RTE_ETHDEV_QUEUE_STAT_CNTRS];
/**< Total number of queue RX packets. */
uint64_t q_opackets[RTE_ETHDEV_QUEUE_STAT_CNTRS];
--
1.9.3
^ permalink raw reply [relevance 9%]
* [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps
@ 2015-06-26 12:59 3% Maryam Tahhan
2015-06-26 12:59 9% ` [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs Maryam Tahhan
2015-07-01 14:27 0% ` [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps Tahhan, Maryam
0 siblings, 2 replies; 200+ results
From: Maryam Tahhan @ 2015-06-26 12:59 UTC (permalink / raw)
To: dev
This patch set implements xstats_get() and xstats_reset() in dev_ops for
ixgbe to expose detailed error statistics to DPDK applications. The
dump_cfg application was extended to demonstrate the usage of
retrieving statistics for DPDK interfaces and renamed to proc_info
in order reflect this new functionality. This patch set also removes non
generic statistics from the statistics strings at the ethdev level and
marks the relevant registers as depricated in struct rte_eth_stats.
v2:
- Fixed patch dependencies.
- Broke down patches into smaller logical changes.
v3:
- Removes non-generic stats fields in rte_stats_strings and deprecates
the fields related to them in struct rte_eth_stats.
- Modifies rte_eth_xstats_get() to return generic stats and extended stats.
Maryam Tahhan (7):
ixgbe: move stats register reads to a new function
ixgbe: add functions to get and reset xstats
ethdev: expose extended error stats
ethdev: remove HW specific stats in stats structs
ixgbe: add NIC specific stats removed from ethdev
app: remove dump_cfg
app: add a new app proc_info
MAINTAINERS | 4 +
app/Makefile | 2 +-
app/dump_cfg/Makefile | 45 ----
app/dump_cfg/main.c | 92 -------
app/proc_info/Makefile | 45 ++++
app/proc_info/main.c | 512 +++++++++++++++++++++++++++++++++++++++
doc/guides/rel_notes/abi.rst | 11 +
drivers/net/ixgbe/ixgbe_ethdev.c | 192 ++++++++++++---
lib/librte_ether/rte_ethdev.c | 29 ++-
lib/librte_ether/rte_ethdev.h | 30 ++-
mk/rte.sdktest.mk | 4 +-
11 files changed, 762 insertions(+), 204 deletions(-)
delete mode 100644 app/dump_cfg/Makefile
delete mode 100644 app/dump_cfg/main.c
create mode 100644 app/proc_info/Makefile
create mode 100644 app/proc_info/main.c
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v5 8/9] doc: announce ABI change of librte_malloc
2015-06-26 11:32 4% ` [dpdk-dev] [PATCH v5 0/9] Dynamic memzones Sergio Gonzalez Monroy
2015-06-26 11:32 1% ` [dpdk-dev] [PATCH v5 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
@ 2015-06-26 11:32 14% ` Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-26 11:32 UTC (permalink / raw)
To: dev
Announce the creation of dummy malloc library for 2.1 and removal of
such library, now integrated in librte_eal, for 2.2 release.
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
doc/guides/rel_notes/abi.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..2aaf900 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,4 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* librte_malloc library has been integrated into librte_eal. The 2.1 release creates a dummy/empty malloc library to fulfill binaries with dynamic linking dependencies on librte_malloc.so. Such dummy library will not be created from release 2.2 so binaries will need to be rebuilt.
--
1.9.3
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v5 0/9] Dynamic memzones
2015-06-19 17:21 4% ` [dpdk-dev] [PATCH v3 0/9] Dynamic memzone Sergio Gonzalez Monroy
2015-06-25 14:05 4% ` [dpdk-dev] [PATCH v4 0/9] Dynamic memzone Sergio Gonzalez Monroy
@ 2015-06-26 11:32 4% ` Sergio Gonzalez Monroy
2015-06-26 11:32 1% ` [dpdk-dev] [PATCH v5 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-26 11:32 14% ` [dpdk-dev] [PATCH v5 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
3 siblings, 2 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-26 11:32 UTC (permalink / raw)
To: dev
Current implemetation allows reserving/creating memzones but not the opposite
(unreserve/free). This affects mempools and other memzone based objects.
>From my point of view, implementing free functionality for memzones would look
like malloc over memsegs.
Thus, this approach moves malloc inside eal (which in turn removes a circular
dependency), where malloc heaps are composed of memsegs.
We keep both malloc and memzone APIs as they are, but memzones allocate its
memory by calling malloc_heap_alloc.
Some extra functionality is required in malloc to allow for boundary constrained
memory requests.
In summary, currently malloc is based on memzones, and with this approach
memzones are based on malloc.
v5:
- Fix rte_memzone_free
- Improve rte_memzone_free unit test
v4:
- Rebase and fix couple of merge issues
v3:
- Create dummy librte_malloc
- Add deprecation notice
- Rework some of the code
- Doc update
- checkpatch
v2:
- New rte_memzone_free
- Support memzone len = 0
- Add all available memsegs to malloc heap at init
- Update memzone/malloc unit tests
Sergio Gonzalez Monroy (9):
eal: move librte_malloc to eal/common
eal: memzone allocated by malloc
app/test: update malloc/memzone unit tests
config: remove CONFIG_RTE_MALLOC_MEMZONE_SIZE
eal: remove free_memseg and references to it
eal: new rte_memzone_free
app/test: update unit test with rte_memzone_free
doc: announce ABI change of librte_malloc
doc: update malloc documentation
MAINTAINERS | 9 +-
app/test/test_malloc.c | 86 ----
app/test/test_memzone.c | 454 ++++------------------
config/common_bsdapp | 8 +-
config/common_linuxapp | 8 +-
doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++++++++-
doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 80952 bytes
doc/guides/prog_guide/index.rst | 1 -
doc/guides/prog_guide/malloc_lib.rst | 233 -----------
doc/guides/prog_guide/overview.rst | 11 +-
doc/guides/rel_notes/abi.rst | 1 +
drivers/net/af_packet/Makefile | 1 -
drivers/net/bonding/Makefile | 1 -
drivers/net/e1000/Makefile | 2 +-
drivers/net/enic/Makefile | 2 +-
drivers/net/fm10k/Makefile | 2 +-
drivers/net/i40e/Makefile | 2 +-
drivers/net/ixgbe/Makefile | 2 +-
drivers/net/mlx4/Makefile | 1 -
drivers/net/null/Makefile | 1 -
drivers/net/pcap/Makefile | 1 -
drivers/net/virtio/Makefile | 2 +-
drivers/net/vmxnet3/Makefile | 2 +-
drivers/net/xenvirt/Makefile | 2 +-
lib/Makefile | 2 +-
lib/librte_acl/Makefile | 2 +-
lib/librte_eal/bsdapp/eal/Makefile | 4 +-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 19 +
lib/librte_eal/common/Makefile | 1 +
lib/librte_eal/common/eal_common_memzone.c | 340 +++++++---------
lib/librte_eal/common/include/rte_eal_memconfig.h | 5 +-
lib/librte_eal/common/include/rte_malloc.h | 342 ++++++++++++++++
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/include/rte_memzone.h | 11 +
lib/librte_eal/common/malloc_elem.c | 344 ++++++++++++++++
lib/librte_eal/common/malloc_elem.h | 192 +++++++++
lib/librte_eal/common/malloc_heap.c | 206 ++++++++++
lib/librte_eal/common/malloc_heap.h | 70 ++++
lib/librte_eal/common/rte_malloc.c | 259 ++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 4 +-
lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 +-
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 19 +
lib/librte_hash/Makefile | 2 +-
lib/librte_lpm/Makefile | 2 +-
lib/librte_malloc/Makefile | 6 +-
lib/librte_malloc/malloc_elem.c | 320 ---------------
lib/librte_malloc/malloc_elem.h | 190 ---------
lib/librte_malloc/malloc_heap.c | 208 ----------
lib/librte_malloc/malloc_heap.h | 70 ----
lib/librte_malloc/rte_malloc.c | 228 +----------
lib/librte_malloc/rte_malloc.h | 342 ----------------
lib/librte_malloc/rte_malloc_version.map | 16 -
lib/librte_mempool/Makefile | 2 -
lib/librte_port/Makefile | 1 -
lib/librte_ring/Makefile | 3 +-
lib/librte_table/Makefile | 1 -
56 files changed, 1929 insertions(+), 2354 deletions(-)
delete mode 100644 doc/guides/prog_guide/malloc_lib.rst
create mode 100644 lib/librte_eal/common/include/rte_malloc.h
create mode 100644 lib/librte_eal/common/malloc_elem.c
create mode 100644 lib/librte_eal/common/malloc_elem.h
create mode 100644 lib/librte_eal/common/malloc_heap.c
create mode 100644 lib/librte_eal/common/malloc_heap.h
create mode 100644 lib/librte_eal/common/rte_malloc.c
delete mode 100644 lib/librte_malloc/malloc_elem.c
delete mode 100644 lib/librte_malloc/malloc_elem.h
delete mode 100644 lib/librte_malloc/malloc_heap.c
delete mode 100644 lib/librte_malloc/malloc_heap.h
delete mode 100644 lib/librte_malloc/rte_malloc.h
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v5 2/9] eal: memzone allocated by malloc
2015-06-26 11:32 4% ` [dpdk-dev] [PATCH v5 0/9] Dynamic memzones Sergio Gonzalez Monroy
@ 2015-06-26 11:32 1% ` Sergio Gonzalez Monroy
2015-06-26 11:32 14% ` [dpdk-dev] [PATCH v5 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-26 11:32 UTC (permalink / raw)
To: dev
In the current memory hierarchy, memsegs are groups of physically
contiguous hugepages, memzones are slices of memsegs and malloc further
slices memzones into smaller memory chunks.
This patch modifies malloc so it partitions memsegs instead of memzones.
Thus memzones would call malloc internally for memory allocation while
maintaining its ABI.
It would be possible to free memzones and therefore any other structure
based on memzones, ie. mempools
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
lib/librte_eal/common/eal_common_memzone.c | 274 ++++++----------------
lib/librte_eal/common/include/rte_eal_memconfig.h | 2 +-
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/malloc_elem.c | 68 ++++--
lib/librte_eal/common/malloc_elem.h | 14 +-
lib/librte_eal/common/malloc_heap.c | 140 ++++++-----
lib/librte_eal/common/malloc_heap.h | 6 +-
lib/librte_eal/common/rte_malloc.c | 7 +-
8 files changed, 197 insertions(+), 317 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index aee184a..943012b 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -50,15 +50,15 @@
#include <rte_string_fns.h>
#include <rte_common.h>
+#include "malloc_heap.h"
+#include "malloc_elem.h"
#include "eal_private.h"
-/* internal copy of free memory segments */
-static struct rte_memseg *free_memseg = NULL;
-
static inline const struct rte_memzone *
memzone_lookup_thread_unsafe(const char *name)
{
const struct rte_mem_config *mcfg;
+ const struct rte_memzone *mz;
unsigned i = 0;
/* get pointer to global configuration */
@@ -68,8 +68,9 @@ memzone_lookup_thread_unsafe(const char *name)
* the algorithm is not optimal (linear), but there are few
* zones and this function should be called at init only
*/
- for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) {
- if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE))
+ for (i = 0; i < RTE_MAX_MEMZONE; i++) {
+ mz = &mcfg->memzone[i];
+ if (mz->addr != NULL && !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE))
return &mcfg->memzone[i];
}
@@ -88,39 +89,45 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id,
len, socket_id, flags, RTE_CACHE_LINE_SIZE);
}
-/*
- * Helper function for memzone_reserve_aligned_thread_unsafe().
- * Calculate address offset from the start of the segment.
- * Align offset in that way that it satisfy istart alignmnet and
- * buffer of the requested length would not cross specified boundary.
- */
-static inline phys_addr_t
-align_phys_boundary(const struct rte_memseg *ms, size_t len, size_t align,
- size_t bound)
+/* Find the heap with the greatest free block size */
+static void
+find_heap_max_free_elem(int *s, size_t *len, unsigned align)
{
- phys_addr_t addr_offset, bmask, end, start;
- size_t step;
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- step = RTE_MAX(align, bound);
- bmask = ~((phys_addr_t)bound - 1);
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate offset to closest alignment */
- start = RTE_ALIGN_CEIL(ms->phys_addr, align);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size > *len) {
+ *len = stats.greatest_free_size;
+ *s = i;
+ }
+ }
+ *len -= (MALLOC_ELEM_OVERHEAD + align);
+}
- while (addr_offset + len < ms->len) {
+/* Find a heap that can allocate the requested size */
+static void
+find_heap_suitable(int *s, size_t len, unsigned align)
+{
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- /* check, do we meet boundary condition */
- end = start + len - (len != 0);
- if ((start & bmask) == (end & bmask))
- break;
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate next offset */
- start = RTE_ALIGN_CEIL(start + 1, step);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size >= len + MALLOC_ELEM_OVERHEAD + align) {
+ *s = i;
+ break;
+ }
}
-
- return addr_offset;
}
static const struct rte_memzone *
@@ -128,13 +135,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
int socket_id, unsigned flags, unsigned align, unsigned bound)
{
struct rte_mem_config *mcfg;
- unsigned i = 0;
- int memseg_idx = -1;
- uint64_t addr_offset, seg_offset = 0;
size_t requested_len;
- size_t memseg_len = 0;
- phys_addr_t memseg_physaddr;
- void *memseg_addr;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
@@ -166,7 +167,6 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
if (align < RTE_CACHE_LINE_SIZE)
align = RTE_CACHE_LINE_SIZE;
-
/* align length on cache boundary. Check for overflow before doing so */
if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) {
rte_errno = EINVAL; /* requested size too big */
@@ -180,129 +180,50 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len);
/* check that boundary condition is valid */
- if (bound != 0 &&
- (requested_len > bound || !rte_is_power_of_2(bound))) {
+ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) {
rte_errno = EINVAL;
return NULL;
}
- /* find the smallest segment matching requirements */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- /* last segment */
- if (free_memseg[i].addr == NULL)
- break;
+ if (len == 0) {
+ if (bound != 0)
+ requested_len = bound;
+ else
+ requested_len = 0;
+ }
- /* empty segment, skip it */
- if (free_memseg[i].len == 0)
- continue;
-
- /* bad socket ID */
- if (socket_id != SOCKET_ID_ANY &&
- free_memseg[i].socket_id != SOCKET_ID_ANY &&
- socket_id != free_memseg[i].socket_id)
- continue;
-
- /*
- * calculate offset to closest alignment that
- * meets boundary conditions.
- */
- addr_offset = align_phys_boundary(free_memseg + i,
- requested_len, align, bound);
-
- /* check len */
- if ((requested_len + addr_offset) > free_memseg[i].len)
- continue;
-
- /* check flags for hugepage sizes */
- if ((flags & RTE_MEMZONE_2MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_1G)
- continue;
- if ((flags & RTE_MEMZONE_1GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_2M)
- continue;
- if ((flags & RTE_MEMZONE_16MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16G)
- continue;
- if ((flags & RTE_MEMZONE_16GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16M)
- continue;
-
- /* this segment is the best until now */
- if (memseg_idx == -1) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- /* find the biggest contiguous zone */
- else if (len == 0) {
- if (free_memseg[i].len > memseg_len) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- }
- /*
- * find the smallest (we already checked that current
- * zone length is > len
- */
- else if (free_memseg[i].len + align < memseg_len ||
- (free_memseg[i].len <= memseg_len + align &&
- addr_offset < seg_offset)) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
+ if (socket_id == SOCKET_ID_ANY) {
+ if (requested_len == 0)
+ find_heap_max_free_elem(&socket_id, &requested_len, align);
+ else
+ find_heap_suitable(&socket_id, requested_len, align);
+
+ if (socket_id == SOCKET_ID_ANY) {
+ rte_errno = ENOMEM;
+ return NULL;
}
}
- /* no segment found */
- if (memseg_idx == -1) {
- /*
- * If RTE_MEMZONE_SIZE_HINT_ONLY flag is specified,
- * try allocating again without the size parameter otherwise -fail.
- */
- if ((flags & RTE_MEMZONE_SIZE_HINT_ONLY) &&
- ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB)
- || (flags & RTE_MEMZONE_16MB) || (flags & RTE_MEMZONE_16GB)))
- return memzone_reserve_aligned_thread_unsafe(name,
- len, socket_id, 0, align, bound);
-
+ /* allocate memory on heap */
+ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket_id], NULL,
+ requested_len, flags, align, bound);
+ if (mz_addr == NULL) {
rte_errno = ENOMEM;
return NULL;
}
- /* save aligned physical and virtual addresses */
- memseg_physaddr = free_memseg[memseg_idx].phys_addr + seg_offset;
- memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr,
- (uintptr_t) seg_offset);
-
- /* if we are looking for a biggest memzone */
- if (len == 0) {
- if (bound == 0)
- requested_len = memseg_len - seg_offset;
- else
- requested_len = RTE_ALIGN_CEIL(memseg_physaddr + 1,
- bound) - memseg_physaddr;
- }
-
- /* set length to correct value */
- len = (size_t)seg_offset + requested_len;
-
- /* update our internal state */
- free_memseg[memseg_idx].len -= len;
- free_memseg[memseg_idx].phys_addr += len;
- free_memseg[memseg_idx].addr =
- (char *)free_memseg[memseg_idx].addr + len;
+ const struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
/* fill the zone in config */
struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++];
snprintf(mz->name, sizeof(mz->name), "%s", name);
- mz->phys_addr = memseg_physaddr;
- mz->addr = memseg_addr;
- mz->len = requested_len;
- mz->hugepage_sz = free_memseg[memseg_idx].hugepage_sz;
- mz->socket_id = free_memseg[memseg_idx].socket_id;
+ mz->phys_addr = rte_malloc_virt2phy(mz_addr);
+ mz->addr = mz_addr;
+ mz->len = (requested_len == 0 ? elem->size : requested_len);
+ mz->hugepage_sz = elem->ms->hugepage_sz;
+ mz->socket_id = elem->ms->socket_id;
mz->flags = 0;
- mz->memseg_id = memseg_idx;
+ mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg;
return mz;
}
@@ -419,45 +340,6 @@ rte_memzone_dump(FILE *f)
}
/*
- * called by init: modify the free memseg list to have cache-aligned
- * addresses and cache-aligned lengths
- */
-static int
-memseg_sanitize(struct rte_memseg *memseg)
-{
- unsigned phys_align;
- unsigned virt_align;
- unsigned off;
-
- phys_align = memseg->phys_addr & RTE_CACHE_LINE_MASK;
- virt_align = (unsigned long)memseg->addr & RTE_CACHE_LINE_MASK;
-
- /*
- * sanity check: phys_addr and addr must have the same
- * alignment
- */
- if (phys_align != virt_align)
- return -1;
-
- /* memseg is really too small, don't bother with it */
- if (memseg->len < (2 * RTE_CACHE_LINE_SIZE)) {
- memseg->len = 0;
- return 0;
- }
-
- /* align start address */
- off = (RTE_CACHE_LINE_SIZE - phys_align) & RTE_CACHE_LINE_MASK;
- memseg->phys_addr += off;
- memseg->addr = (char *)memseg->addr + off;
- memseg->len -= off;
-
- /* align end address */
- memseg->len &= ~((uint64_t)RTE_CACHE_LINE_MASK);
-
- return 0;
-}
-
-/*
* Init the memzone subsystem
*/
int
@@ -465,14 +347,10 @@ rte_eal_memzone_init(void)
{
struct rte_mem_config *mcfg;
const struct rte_memseg *memseg;
- unsigned i = 0;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
- /* mirror the runtime memsegs from config */
- free_memseg = mcfg->free_memseg;
-
/* secondary processes don't need to initialise anything */
if (rte_eal_process_type() == RTE_PROC_SECONDARY)
return 0;
@@ -485,33 +363,13 @@ rte_eal_memzone_init(void)
rte_rwlock_write_lock(&mcfg->mlock);
- /* fill in uninitialized free_memsegs */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (memseg[i].addr == NULL)
- break;
- if (free_memseg[i].addr != NULL)
- continue;
- memcpy(&free_memseg[i], &memseg[i], sizeof(struct rte_memseg));
- }
-
- /* make all zones cache-aligned */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (free_memseg[i].addr == NULL)
- break;
- if (memseg_sanitize(&free_memseg[i]) < 0) {
- RTE_LOG(ERR, EAL, "%s(): Sanity check failed\n", __func__);
- rte_rwlock_write_unlock(&mcfg->mlock);
- return -1;
- }
- }
-
/* delete all zones */
mcfg->memzone_idx = 0;
memset(mcfg->memzone, 0, sizeof(mcfg->memzone));
rte_rwlock_write_unlock(&mcfg->mlock);
- return 0;
+ return rte_eal_malloc_heap_init();
}
/* Walk all reserved memory zones */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 34f5abc..055212a 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -73,7 +73,7 @@ struct rte_mem_config {
struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */
struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */
- /* Runtime Physmem descriptors. */
+ /* Runtime Physmem descriptors - NOT USED */
struct rte_memseg free_memseg[RTE_MAX_MEMSEG];
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h
index 716216f..b270356 100644
--- a/lib/librte_eal/common/include/rte_malloc_heap.h
+++ b/lib/librte_eal/common/include/rte_malloc_heap.h
@@ -40,7 +40,7 @@
#include <rte_memory.h>
/* Number of free lists per heap, grouped by size. */
-#define RTE_HEAP_NUM_FREELISTS 5
+#define RTE_HEAP_NUM_FREELISTS 13
/**
* Structure to hold malloc heap
@@ -48,7 +48,6 @@
struct malloc_heap {
rte_spinlock_t lock;
LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS];
- unsigned mz_count;
unsigned alloc_count;
size_t total_size;
} __rte_cache_aligned;
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index a5e1248..b54ee33 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -37,7 +37,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include <rte_per_lcore.h>
@@ -56,10 +55,10 @@
*/
void
malloc_elem_init(struct malloc_elem *elem,
- struct malloc_heap *heap, const struct rte_memzone *mz, size_t size)
+ struct malloc_heap *heap, const struct rte_memseg *ms, size_t size)
{
elem->heap = heap;
- elem->mz = mz;
+ elem->ms = ms;
elem->prev = NULL;
memset(&elem->free_list, 0, sizeof(elem->free_list));
elem->state = ELEM_FREE;
@@ -70,12 +69,12 @@ malloc_elem_init(struct malloc_elem *elem,
}
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
{
- malloc_elem_init(elem, prev->heap, prev->mz, 0);
+ malloc_elem_init(elem, prev->heap, prev->ms, 0);
elem->prev = prev;
elem->state = ELEM_BUSY; /* mark busy so its never merged */
}
@@ -86,12 +85,24 @@ malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
* fit, return NULL.
*/
static void *
-elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
+elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- const uintptr_t end_pt = (uintptr_t)elem +
+ const size_t bmask = ~(bound - 1);
+ uintptr_t end_pt = (uintptr_t)elem +
elem->size - MALLOC_ELEM_TRAILER_LEN;
- const uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
- const uintptr_t new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
+ uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ uintptr_t new_elem_start;
+
+ /* check boundary */
+ if ((new_data_start & bmask) != ((end_pt - 1) & bmask)) {
+ end_pt = RTE_ALIGN_FLOOR(end_pt, bound);
+ new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ if (((end_pt - 1) & bmask) != (new_data_start & bmask))
+ return NULL;
+ }
+
+ new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
/* if the new start point is before the exist start, it won't fit */
return (new_elem_start < (uintptr_t)elem) ? NULL : (void *)new_elem_start;
@@ -102,9 +113,10 @@ elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
* alignment request from the current element
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- return elem_start_pt(elem, size, align) != NULL;
+ return elem_start_pt(elem, size, align, bound) != NULL;
}
/*
@@ -115,10 +127,10 @@ static void
split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)
{
struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size);
- const unsigned old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
- const unsigned new_elem_size = elem->size - old_elem_size;
+ const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
+ const size_t new_elem_size = elem->size - old_elem_size;
- malloc_elem_init(split_pt, elem->heap, elem->mz, new_elem_size);
+ malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size);
split_pt->prev = elem;
next_elem->prev = split_pt;
elem->size = old_elem_size;
@@ -168,8 +180,9 @@ malloc_elem_free_list_index(size_t size)
void
malloc_elem_free_list_insert(struct malloc_elem *elem)
{
- size_t idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
+ size_t idx;
+ idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
elem->state = ELEM_FREE;
LIST_INSERT_HEAD(&elem->heap->free_head[idx], elem, free_list);
}
@@ -190,12 +203,26 @@ elem_free_list_remove(struct malloc_elem *elem)
* is not done here, as it's done there previously.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- struct malloc_elem *new_elem = elem_start_pt(elem, size, align);
- const unsigned old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound);
+ const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ const size_t trailer_size = elem->size - old_elem_size - size -
+ MALLOC_ELEM_OVERHEAD;
+
+ elem_free_list_remove(elem);
- if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE){
+ if (trailer_size > MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* split it, too much free space after elem */
+ struct malloc_elem *new_free_elem =
+ RTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD);
+
+ split_elem(elem, new_free_elem);
+ malloc_elem_free_list_insert(new_free_elem);
+ }
+
+ if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
/* don't split it, pad the element instead */
elem->state = ELEM_BUSY;
elem->pad = old_elem_size;
@@ -208,8 +235,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
new_elem->size = elem->size - elem->pad;
set_header(new_elem);
}
- /* remove element from free list */
- elem_free_list_remove(elem);
return new_elem;
}
@@ -219,7 +244,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
* Re-insert original element, in case its new size makes it
* belong on a different list.
*/
- elem_free_list_remove(elem);
split_elem(elem, new_elem);
new_elem->state = ELEM_BUSY;
malloc_elem_free_list_insert(elem);
diff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h
index 9790b1a..e05d2ea 100644
--- a/lib/librte_eal/common/malloc_elem.h
+++ b/lib/librte_eal/common/malloc_elem.h
@@ -47,9 +47,9 @@ enum elem_state {
struct malloc_elem {
struct malloc_heap *heap;
- struct malloc_elem *volatile prev; /* points to prev elem in memzone */
+ struct malloc_elem *volatile prev; /* points to prev elem in memseg */
LIST_ENTRY(malloc_elem) free_list; /* list of free elements in heap */
- const struct rte_memzone *mz;
+ const struct rte_memseg *ms;
volatile enum elem_state state;
uint32_t pad;
size_t size;
@@ -136,11 +136,11 @@ malloc_elem_from_data(const void *data)
void
malloc_elem_init(struct malloc_elem *elem,
struct malloc_heap *heap,
- const struct rte_memzone *mz,
+ const struct rte_memseg *ms,
size_t size);
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem,
@@ -151,14 +151,16 @@ malloc_elem_mkend(struct malloc_elem *elem,
* of the requested size and with the requested alignment
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* reserve a block of data in an existing malloc_elem. If the malloc_elem
* is much larger than the data block requested, we split the element in two.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_alloc(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* free a malloc_elem block by adding it to the free list. If the
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 8861d27..f5fff96 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -39,7 +39,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_launch.h>
@@ -54,123 +53,104 @@
#include "malloc_elem.h"
#include "malloc_heap.h"
-/* since the memzone size starts with a digit, it will appear unquoted in
- * rte_config.h, so quote it so it can be passed to rte_str_to_size */
-#define MALLOC_MEMZONE_SIZE RTE_STR(RTE_MALLOC_MEMZONE_SIZE)
-
-/*
- * returns the configuration setting for the memzone size as a size_t value
- */
-static inline size_t
-get_malloc_memzone_size(void)
+static unsigned
+check_hugepage_sz(unsigned flags, size_t hugepage_sz)
{
- return rte_str_to_size(MALLOC_MEMZONE_SIZE);
+ unsigned ret = 1;
+
+ if ((flags & RTE_MEMZONE_2MB) && hugepage_sz == RTE_PGSIZE_1G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_1GB) && hugepage_sz == RTE_PGSIZE_2M)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16MB) && hugepage_sz == RTE_PGSIZE_16G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16GB) && hugepage_sz == RTE_PGSIZE_16M)
+ ret = 0;
+
+ return ret;
}
/*
- * reserve an extra memory zone and make it available for use by a particular
- * heap. This reserves the zone and sets a dummy malloc_elem header at the end
+ * Expand the heap with a memseg.
+ * This reserves the zone and sets a dummy malloc_elem header at the end
* to prevent overflow. The rest of the zone is added to free list as a single
* large free block
*/
-static int
-malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
+static void
+malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)
{
- const unsigned mz_flags = 0;
- const size_t block_size = get_malloc_memzone_size();
- /* ensure the data we want to allocate will fit in the memzone */
- const size_t min_size = size + align + MALLOC_ELEM_OVERHEAD * 2;
- const struct rte_memzone *mz = NULL;
- struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
- unsigned numa_socket = heap - mcfg->malloc_heaps;
-
- size_t mz_size = min_size;
- if (mz_size < block_size)
- mz_size = block_size;
-
- char mz_name[RTE_MEMZONE_NAMESIZE];
- snprintf(mz_name, sizeof(mz_name), "MALLOC_S%u_HEAP_%u",
- numa_socket, heap->mz_count++);
-
- /* try getting a block. if we fail and we don't need as big a block
- * as given in the config, we can shrink our request and try again
- */
- do {
- mz = rte_memzone_reserve(mz_name, mz_size, numa_socket,
- mz_flags);
- if (mz == NULL)
- mz_size /= 2;
- } while (mz == NULL && mz_size > min_size);
- if (mz == NULL)
- return -1;
-
/* allocate the memory block headers, one at end, one at start */
- struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
- struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
- mz_size - MALLOC_ELEM_OVERHEAD);
+ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr;
+ struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr,
+ ms->len - MALLOC_ELEM_OVERHEAD);
end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);
+ const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- malloc_elem_init(start_elem, heap, mz, elem_size);
+ malloc_elem_init(start_elem, heap, ms, elem_size);
malloc_elem_mkend(end_elem, start_elem);
malloc_elem_free_list_insert(start_elem);
- /* increase heap total size by size of new memzone */
- heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
- return 0;
+ heap->total_size += elem_size;
}
/*
* Iterates through the freelist for a heap to find a free element
* which can store data of the required size and with the requested alignment.
+ * If size is 0, find the biggest available elem.
* Returns null on failure, or pointer to element on success.
*/
static struct malloc_elem *
-find_suitable_element(struct malloc_heap *heap, size_t size, unsigned align)
+find_suitable_element(struct malloc_heap *heap, size_t size,
+ unsigned flags, size_t align, size_t bound)
{
size_t idx;
- struct malloc_elem *elem;
+ struct malloc_elem *elem, *alt_elem = NULL;
for (idx = malloc_elem_free_list_index(size);
- idx < RTE_HEAP_NUM_FREELISTS; idx++)
- {
+ idx < RTE_HEAP_NUM_FREELISTS; idx++) {
for (elem = LIST_FIRST(&heap->free_head[idx]);
- !!elem; elem = LIST_NEXT(elem, free_list))
- {
- if (malloc_elem_can_hold(elem, size, align))
- return elem;
+ !!elem; elem = LIST_NEXT(elem, free_list)) {
+ if (malloc_elem_can_hold(elem, size, align, bound)) {
+ if (check_hugepage_sz(flags, elem->ms->hugepage_sz))
+ return elem;
+ alt_elem = elem;
+ }
}
}
+
+ if ((alt_elem != NULL) && (flags & RTE_MEMZONE_SIZE_HINT_ONLY))
+ return alt_elem;
+
return NULL;
}
/*
- * Main function called by malloc to allocate a block of memory from the
- * heap. It locks the free list, scans it, and adds a new memzone if the
- * scan fails. Once the new memzone is added, it re-scans and should return
+ * Main function to allocate a block of memory from the heap.
+ * It locks the free list, scans it, and adds a new memseg if the
+ * scan fails. Once the new memseg is added, it re-scans and should return
* the new element after releasing the lock.
*/
void *
malloc_heap_alloc(struct malloc_heap *heap,
- const char *type __attribute__((unused)), size_t size, unsigned align)
+ const char *type __attribute__((unused)), size_t size, unsigned flags,
+ size_t align, size_t bound)
{
+ struct malloc_elem *elem;
+
size = RTE_CACHE_LINE_ROUNDUP(size);
align = RTE_CACHE_LINE_ROUNDUP(align);
+
rte_spinlock_lock(&heap->lock);
- struct malloc_elem *elem = find_suitable_element(heap, size, align);
- if (elem == NULL){
- if ((malloc_heap_add_memzone(heap, size, align)) == 0)
- elem = find_suitable_element(heap, size, align);
- }
- if (elem != NULL){
- elem = malloc_elem_alloc(elem, size, align);
+ elem = find_suitable_element(heap, size, flags, align, bound);
+ if (elem != NULL) {
+ elem = malloc_elem_alloc(elem, size, align, bound);
/* increase heap's count of allocated elements */
heap->alloc_count++;
}
rte_spinlock_unlock(&heap->lock);
- return elem == NULL ? NULL : (void *)(&elem[1]);
+ return elem == NULL ? NULL : (void *)(&elem[1]);
}
/*
@@ -206,3 +186,21 @@ malloc_heap_get_stats(const struct malloc_heap *heap,
socket_stats->alloc_count = heap->alloc_count;
return 0;
}
+
+int
+rte_eal_malloc_heap_init(void)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ unsigned ms_cnt;
+ struct rte_memseg *ms;
+
+ if (mcfg == NULL)
+ return -1;
+
+ for (ms = &mcfg->memseg[0], ms_cnt = 0;
+ (ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0);
+ ms_cnt++, ms++)
+ malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms);
+
+ return 0;
+}
diff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h
index a47136d..3ccbef0 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -53,15 +53,15 @@ malloc_get_numa_socket(void)
}
void *
-malloc_heap_alloc(struct malloc_heap *heap, const char *type,
- size_t size, unsigned align);
+malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size,
+ unsigned flags, size_t align, size_t bound);
int
malloc_heap_get_stats(const struct malloc_heap *heap,
struct rte_malloc_socket_stats *socket_stats);
int
-rte_eal_heap_memzone_init(void);
+rte_eal_malloc_heap_init(void);
#ifdef __cplusplus
}
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index c313a57..54c2bd8 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -39,7 +39,6 @@
#include <rte_memcpy.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_branch_prediction.h>
@@ -87,7 +86,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
return NULL;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL || socket_arg != SOCKET_ID_ANY)
return ret;
@@ -98,7 +97,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
continue;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL)
return ret;
}
@@ -256,5 +255,5 @@ rte_malloc_virt2phy(const void *addr)
const struct malloc_elem *elem = malloc_elem_from_data(addr);
if (elem == NULL)
return 0;
- return elem->mz->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->mz->addr);
+ return elem->ms->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->ms->addr);
}
--
1.9.3
^ permalink raw reply [relevance 1%]
* Re: [dpdk-dev] [PATCH v4 1/4] ethdev: rename rte_eth_vmdq_mirror_conf
@ 2015-06-26 7:03 5% ` Wu, Jingjing
2015-07-06 1:27 0% ` Wu, Jingjing
0 siblings, 1 reply; 200+ results
From: Wu, Jingjing @ 2015-06-26 7:03 UTC (permalink / raw)
To: 'nhorman@tuxdriver.com'; +Cc: dev
Hi, Neil
About this patch I have an ABI concern about it.
This patch just renamed a struct rte_eth_vmdq_mirror_conf to rte_eth_mirror_conf, the size and its elements don't change. As my understanding, it will not break the ABI. And I also tested it.
But when I use the script ./scripts/validate-abi.sh to check. A low severity problem is reported in symbol "rte_eth_mirror_rule_set"
- Change: "Base type of 2nd parameter mirror_conf has been changed from struct rte_eth_vmdq_mirror_conf to struct rte_eth_mirror_conf."
- Effect: "Replacement of parameter base type may indicate a change in its semantic meaning."
So, I'm not sure whether this patch meet the ABI policy?
Additional, about the validate-abi.sh, does it mean we need to fix all the problems it reports? Or we can decide case by case. Can a Low Severity problem be acceptable?
Look forward to your reply.
Thanks
Jingjing
> -----Original Message-----
> From: Wu, Jingjing
> Sent: Wednesday, June 10, 2015 2:25 PM
> To: dev@dpdk.org
> Cc: Wu, Jingjing; Liu, Jijiang; Jiajia, SunX; Zhang, Helin
> Subject: [PATCH v4 1/4] ethdev: rename rte_eth_vmdq_mirror_conf
>
> rename rte_eth_vmdq_mirror_conf to rte_eth_mirror_conf and move the
> maximum rule id check from ethdev level to driver
>
> Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
> ---
> app/test-pmd/cmdline.c | 22 +++++++++++-----------
> drivers/net/ixgbe/ixgbe_ethdev.c | 11 +++++++----
> drivers/net/ixgbe/ixgbe_ethdev.h | 4 +++-
> lib/librte_ether/rte_ethdev.c | 18 ++----------------
> lib/librte_ether/rte_ethdev.h | 19 ++++++++++---------
> 5 files changed, 33 insertions(+), 41 deletions(-)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> f01db2a..d693bde 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -6604,11 +6604,11 @@ cmd_set_mirror_mask_parsed(void
> *parsed_result, {
> int ret,nb_item,i;
> struct cmd_set_mirror_mask_result *res = parsed_result;
> - struct rte_eth_vmdq_mirror_conf mr_conf;
> + struct rte_eth_mirror_conf mr_conf;
>
> - memset(&mr_conf,0,sizeof(struct rte_eth_vmdq_mirror_conf));
> + memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
>
> - unsigned int vlan_list[ETH_VMDQ_MAX_VLAN_FILTERS];
> + unsigned int vlan_list[ETH_MIRROR_MAX_VLANS];
>
> mr_conf.dst_pool = res->dstpool_id;
>
> @@ -6618,11 +6618,11 @@ cmd_set_mirror_mask_parsed(void
> *parsed_result,
> } else if(!strcmp(res->what, "vlan-mirror")) {
> mr_conf.rule_type_mask = ETH_VMDQ_VLAN_MIRROR;
> nb_item = parse_item_list(res->value, "core",
> -
> ETH_VMDQ_MAX_VLAN_FILTERS,vlan_list,1);
> + ETH_MIRROR_MAX_VLANS, vlan_list,
> 1);
> if (nb_item <= 0)
> return;
>
> - for(i=0; i < nb_item; i++) {
> + for (i = 0; i < nb_item; i++) {
> if (vlan_list[i] > ETHER_MAX_VLAN_ID) {
> printf("Invalid vlan_id: must be < 4096\n");
> return;
> @@ -6634,10 +6634,10 @@ cmd_set_mirror_mask_parsed(void
> *parsed_result,
> }
>
> if(!strcmp(res->on, "on"))
> - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> res->rule_id, 1);
> else
> - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> res->rule_id, 0);
> if(ret < 0)
> printf("mirror rule add error: (%s)\n", strerror(-ret)); @@ -
> 6711,9 +6711,9 @@ cmd_set_mirror_link_parsed(void *parsed_result, {
> int ret;
> struct cmd_set_mirror_link_result *res = parsed_result;
> - struct rte_eth_vmdq_mirror_conf mr_conf;
> + struct rte_eth_mirror_conf mr_conf;
>
> - memset(&mr_conf,0,sizeof(struct rte_eth_vmdq_mirror_conf));
> + memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
> if(!strcmp(res->what, "uplink-mirror")) {
> mr_conf.rule_type_mask = ETH_VMDQ_UPLINK_MIRROR;
> }else if(!strcmp(res->what, "downlink-mirror")) @@ -6722,10
> +6722,10 @@ cmd_set_mirror_link_parsed(void *parsed_result,
> mr_conf.dst_pool = res->dstpool_id;
>
> if(!strcmp(res->on, "on"))
> - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> res->rule_id, 1);
> else
> - ret = rte_eth_mirror_rule_set(res->port_id,&mr_conf,
> + ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
> res->rule_id, 0);
>
> /* check the return value and print it if is < 0 */ diff --git
> a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
> index 0d9f9b2..9e767fa 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -209,7 +209,7 @@ static int ixgbe_set_pool_tx(struct rte_eth_dev
> *dev,uint16_t pool,uint8_t on); static int ixgbe_set_pool_vlan_filter(struct
> rte_eth_dev *dev, uint16_t vlan,
> uint64_t pool_mask,uint8_t vlan_on);
> static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
> - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> + struct rte_eth_mirror_conf *mirror_conf,
> uint8_t rule_id, uint8_t on);
> static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev,
> uint8_t rule_id);
> @@ -3388,7 +3388,7 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev
> *dev, uint16_t vlan,
>
> static int
> ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
> - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> + struct rte_eth_mirror_conf *mirror_conf,
> uint8_t rule_id, uint8_t on)
> {
> uint32_t mr_ctl,vlvf;
> @@ -3412,7 +3412,10 @@ ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
> IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
>
> if (ixgbe_vmdq_mode_check(hw) < 0)
> - return (-ENOTSUP);
> + return -ENOTSUP;
> +
> + if (rule_id >= IXGBE_MAX_MIRROR_RULES)
> + return -EINVAL;
>
> /* Check if vlan mask is valid */
> if ((mirror_conf->rule_type_mask & ETH_VMDQ_VLAN_MIRROR)
> && (on)) { @@ -3526,7 +3529,7 @@ ixgbe_mirror_rule_reset(struct
> rte_eth_dev *dev, uint8_t rule_id)
> return (-ENOTSUP);
>
> memset(&mr_info->mr_conf[rule_id], 0,
> - sizeof(struct rte_eth_vmdq_mirror_conf));
> + sizeof(struct rte_eth_mirror_conf));
>
> /* clear PFVMCTL register */
> IXGBE_WRITE_REG(hw, IXGBE_MRCTL(rule_id), mr_ctl); diff --git
> a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
> index 19237b8..755b674 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.h
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.h
> @@ -177,8 +177,10 @@ struct ixgbe_uta_info {
> uint32_t uta_shadow[IXGBE_MAX_UTA];
> };
>
> +#define IXGBE_MAX_MIRROR_RULES 4 /* Maximum nb. of mirror rules. */
> +
> struct ixgbe_mirror_info {
> - struct rte_eth_vmdq_mirror_conf
> mr_conf[ETH_VMDQ_NUM_MIRROR_RULE];
> + struct rte_eth_mirror_conf mr_conf[IXGBE_MAX_MIRROR_RULES];
> /**< store PF mirror rules configuration*/ };
>
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index 024fe8b..43c7295 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -3034,7 +3034,7 @@ int rte_eth_set_vf_rate_limit(uint8_t port_id,
> uint16_t vf, uint16_t tx_rate,
>
> int
> rte_eth_mirror_rule_set(uint8_t port_id,
> - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> + struct rte_eth_mirror_conf *mirror_conf,
> uint8_t rule_id, uint8_t on)
> {
> struct rte_eth_dev *dev = &rte_eth_devices[port_id]; @@ -3051,7
> +3051,7 @@ rte_eth_mirror_rule_set(uint8_t port_id,
>
> if (mirror_conf->dst_pool >= ETH_64_POOLS) {
> PMD_DEBUG_TRACE("Invalid dst pool, pool id must"
> - "be 0-%d\n",ETH_64_POOLS - 1);
> + "be 0-%d\n", ETH_64_POOLS - 1);
> return -EINVAL;
> }
>
> @@ -3062,13 +3062,6 @@ rte_eth_mirror_rule_set(uint8_t port_id,
> return -EINVAL;
> }
>
> - if(rule_id >= ETH_VMDQ_NUM_MIRROR_RULE)
> - {
> - PMD_DEBUG_TRACE("Invalid rule_id, rule_id must be 0-
> %d\n",
> - ETH_VMDQ_NUM_MIRROR_RULE - 1);
> - return -EINVAL;
> - }
> -
> dev = &rte_eth_devices[port_id];
> FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mirror_rule_set, -
> ENOTSUP);
>
> @@ -3085,13 +3078,6 @@ rte_eth_mirror_rule_reset(uint8_t port_id,
> uint8_t rule_id)
> return -ENODEV;
> }
>
> - if(rule_id >= ETH_VMDQ_NUM_MIRROR_RULE)
> - {
> - PMD_DEBUG_TRACE("Invalid rule_id, rule_id must be 0-
> %d\n",
> - ETH_VMDQ_NUM_MIRROR_RULE-1);
> - return -EINVAL;
> - }
> -
> dev = &rte_eth_devices[port_id];
> FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mirror_rule_reset, -
> ENOTSUP);
>
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 16dbe00..ae22fea 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -467,8 +467,8 @@ struct rte_eth_rss_conf {
> #define ETH_VMDQ_ACCEPT_BROADCAST 0x0008 /**< accept broadcast
> packets. */
> #define ETH_VMDQ_ACCEPT_MULTICAST 0x0010 /**< multicast
> promiscuous. */
>
> -/* Definitions used for VMDQ mirror rules setting */
> -#define ETH_VMDQ_NUM_MIRROR_RULE 4 /**< Maximum nb. of mirror
> rules. . */
> +/** Maximum nb. of vlan per mirror rule */
> +#define ETH_MIRROR_MAX_VLANS 64
>
> #define ETH_VMDQ_POOL_MIRROR 0x0001 /**< Virtual Pool Mirroring. */
> #define ETH_VMDQ_UPLINK_MIRROR 0x0002 /**< Uplink Port Mirroring.
> */ @@ -480,18 +480,19 @@ struct rte_eth_rss_conf {
> */
> struct rte_eth_vlan_mirror {
> uint64_t vlan_mask; /**< mask for valid VLAN ID. */
> - uint16_t vlan_id[ETH_VMDQ_MAX_VLAN_FILTERS];
> - /** VLAN ID list for vlan mirror. */
> + /** VLAN ID list for vlan mirroring. */
> + uint16_t vlan_id[ETH_MIRROR_MAX_VLANS];
> };
>
> /**
> * A structure used to configure traffic mirror of an Ethernet port.
> */
> -struct rte_eth_vmdq_mirror_conf {
> +struct rte_eth_mirror_conf {
> uint8_t rule_type_mask; /**< Mirroring rule type mask we want to
> set */
> - uint8_t dst_pool; /**< Destination pool for this mirror rule. */
> + uint8_t dst_pool; /**< Destination pool for this mirror rule. */
> uint64_t pool_mask; /**< Bitmap of pool for pool mirroring */
> - struct rte_eth_vlan_mirror vlan; /**< VLAN ID setting for VLAN
> mirroring */
> + /** VLAN ID setting for VLAN mirroring. */
> + struct rte_eth_vlan_mirror vlan;
> };
>
> /**
> @@ -1211,7 +1212,7 @@ typedef int (*eth_set_vf_rate_limit_t)(struct
> rte_eth_dev *dev, /**< @internal Set VF TX rate */
>
> typedef int (*eth_mirror_rule_set_t)(struct rte_eth_dev *dev,
> - struct rte_eth_vmdq_mirror_conf
> *mirror_conf,
> + struct rte_eth_mirror_conf *mirror_conf,
> uint8_t rule_id,
> uint8_t on);
> /**< @internal Add a traffic mirroring rule on an Ethernet device */ @@ -
> 3168,7 +3169,7 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t
> vlan_id,
> * - (-EINVAL) if the mr_conf information is not correct.
> */
> int rte_eth_mirror_rule_set(uint8_t port_id,
> - struct rte_eth_vmdq_mirror_conf *mirror_conf,
> + struct rte_eth_mirror_conf *mirror_conf,
> uint8_t rule_id,
> uint8_t on);
>
> --
> 1.9.3
^ permalink raw reply [relevance 5%]
* Re: [dpdk-dev] [PATCH v2 0/4] extend flow director to support L2_paylod type
2015-06-26 2:26 0% ` Xu, HuilongX
@ 2015-06-26 3:14 0% ` Zhang, Helin
1 sibling, 0 replies; 200+ results
From: Zhang, Helin @ 2015-06-26 3:14 UTC (permalink / raw)
To: Wu, Jingjing, dev
> -----Original Message-----
> From: Wu, Jingjing
> Sent: Tuesday, June 16, 2015 11:44 AM
> To: dev@dpdk.org
> Cc: Wu, Jingjing; Zhang, Helin; Xu, HuilongX
> Subject: [PATCH v2 0/4] extend flow director to support L2_paylod type
>
> This patch set extends flow director to support L2_paylod type in i40e driver.
>
> v2 change:
> - remove the flow director VF filtering from this patch to avoid breaking ABI.
>
> Jingjing Wu (4):
> ethdev: add struct rte_eth_l2_flow to support l2_payload flow type
> i40e: extend flow diretcor to support l2_payload flow type
> testpmd: extend commands
> doc: extend commands in testpmd
>
> app/test-pmd/cmdline.c | 48
> +++++++++++++++++++++++++++--
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 ++-
> drivers/net/i40e/i40e_fdir.c | 24 +++++++++++++--
> lib/librte_ether/rte_eth_ctrl.h | 8 +++++
> 4 files changed, 78 insertions(+), 7 deletions(-)
Acked-by: Helin Zhang <helin.zhang@intel.com>
>
> --
> 1.9.3
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v2 0/4] extend flow director to support L2_paylod type
@ 2015-06-26 2:26 0% ` Xu, HuilongX
2015-06-26 3:14 0% ` Zhang, Helin
1 sibling, 0 replies; 200+ results
From: Xu, HuilongX @ 2015-06-26 2:26 UTC (permalink / raw)
To: Wu, Jingjing, dev
Tested-by:huilong,xu <huilongx.xu@intel.com>
Os: 3.11.10-301.fc20.x86_64
Gcc: gcc version 4.8.3 20140911 (Red Hat 4.8.3-7) (GCC)
Package: d2c08067240baf27f2447bf4981b9ab58ce74d35 + l2payload patch
NIC: Intel Corporation Ethernet Controller XL710 for 40GbE QSFP+ [8086:1583]
Test case Summary: 1 case passed
Test sets:
1. build dpdk with x86_64 gcc target
2. set hugpage and bind igb_uio to Fortville nic
3. ./testpmd -c ffff -n 4 -- -I --portmask=0x3 --disable-rss --rxq=2 --txq=2 --nbcores=8 --pkt-filter-mode=perfect
4. exec testpmd cmdline
a) set verbose 1
b) set fwd rxonly
c) flow_director_filter 0 add flow l2_payload ether 0x0806 flexbytes () fwd queue 1 fd 1
d) start
5. send a arp package to port 0
6. testpmd print port 0 queue 1 received a pachage
> -----Original Message-----
> From: Wu, Jingjing
> Sent: Tuesday, June 16, 2015 11:44 AM
> To: dev@dpdk.org
> Cc: Wu, Jingjing; Zhang, Helin; Xu, HuilongX
> Subject: [PATCH v2 0/4] extend flow director to support L2_paylod type
>
> This patch set extends flow director to support L2_paylod type in i40e
> driver.
>
> v2 change:
> - remove the flow director VF filtering from this patch to avoid breaking
> ABI.
>
> Jingjing Wu (4):
> ethdev: add struct rte_eth_l2_flow to support l2_payload flow type
> i40e: extend flow diretcor to support l2_payload flow type
> testpmd: extend commands
> doc: extend commands in testpmd
>
> app/test-pmd/cmdline.c | 48
> +++++++++++++++++++++++++++--
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 ++-
> drivers/net/i40e/i40e_fdir.c | 24 +++++++++++++--
> lib/librte_ether/rte_eth_ctrl.h | 8 +++++
> 4 files changed, 78 insertions(+), 7 deletions(-)
>
> --
> 1.9.3
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH v2 10/11] doc: announce ABI change of librte_hash
2015-06-25 22:05 4% ` [dpdk-dev] [PATCH v2 00/11] Cuckoo hash Pablo de Lara
@ 2015-06-25 22:05 14% ` Pablo de Lara
2015-06-28 22:25 4% ` [dpdk-dev] [PATCH v3 00/11] Cuckoo hash Pablo de Lara
2 siblings, 0 replies; 200+ results
From: Pablo de Lara @ 2015-06-25 22:05 UTC (permalink / raw)
To: dev
rte_hash structure is now private for version 2.1, and two
of the macros in rte_hash.h are now deprecated, so this patch
adds notice of these changes.
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---
doc/guides/rel_notes/abi.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..fae09fd 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,5 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* Structure rte_hash in librte_hash library has been changed and has been made private in relese 2.1, as applications should have never accessed to its internal data (library should have been marked as internal).
+* The Macros #RTE_HASH_BUCKET_ENTRIES_MAX and #RTE_HASH_KEY_LENGTH_MAX are deprecated and will be removed with version 2.2.
--
2.4.2
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v2 00/11] Cuckoo hash
@ 2015-06-25 22:05 4% ` Pablo de Lara
` (2 more replies)
1 sibling, 3 replies; 200+ results
From: Pablo de Lara @ 2015-06-25 22:05 UTC (permalink / raw)
To: dev
This patchset is to replace the existing hash library with
a more efficient and functional approach, using the Cuckoo hash
method to deal with collisions. This method is based on using
two different hash functions to have two possible locations
in the hash table where an entry can be.
So, if a bucket is full, a new entry can push one of the items
in that bucket to its alternative location, making space for itself.
Advantages
~~~~~~~
- Offers the option to store more entries when the target bucket is full
(unlike the previous implementation)
- Memory efficient: for storing those entries, it is not necessary to
request new memory, as the entries will be stored in the same table
- Constant worst lookup time: in worst case scenario, it always takes
the same time to look up an entry, as there are only two possible locations
where an entry can be.
- Storing data: user can store data in the hash table, unlike the
previous implementation, but he can still use the old API
This implementation tipically offers over 90% utilization.
Notice that API has been extended, but old API remains. The main
change in ABI is that rte_hash structure is now private and the
deprecation of two macros.
Changes in v2:
- Fixed issue where table could not store maximum number of entries
- Fixed issue where lookup burst could not be more than 32 (instead of 64)
- Remove unnecessary macros and add other useful ones
- Added missing library dependencies
- Used directly rte_hash_secondary instead of rte_hash_alt
- Renamed rte_hash.c to rte_cuckoo_hash.c to ease the view of the new library
- Renamed test_hash_perf.c temporarily to ease the view of the improved unit test
- Moved rte_hash, rte_bucket and rte_hash_key structures to rte_cuckoo_hash.c to
make them private
- Corrected copyright dates
- Added an optimized function to compare keys that are multiple of 16 bytes
- Improved the way to use primary/secondary signatures. Now both are stored in
the bucket, so there is no need to calculate them if required.
Also, there is no need to use the MSB of a signature to differenciate between
an empty entry and signature 0, since we are storing both signatures,
which cannot be both 0.
- Removed rte_hash_rehash, as it was a very expensive operation.
Therefore, the add function returns now -ENOSPC if key cannot be added
because of a loop.
- Prefetched new slot for new key in add function to improve performance.
- Made doxygen comments more clear.
- Removed unnecessary rte_hash_del_key_data and rte_hash_del_key_with_data,
as we can use the lookup functions if we want to get the data before deleting.
- Removed some unnecessary includes in rte_hash.h
- Removed some unnecessary variables in rte_cuckoo_hash.c
- Removed some unnecessary checks before creating a new hash table
- Added documentation (in release notes and programmers guide)
- Added new unit tests and replaced the performance one for hash tables
Pablo de Lara (11):
eal: add const in prefetch functions
hash: move rte_hash structure to C file and make it internal
test/hash: enhance hash unit tests
test/hash: rename new hash perf unit test back to original name
hash: replace existing hash library with cuckoo hash implementation
hash: add new lookup_bulk_with_hash function
hash: add new function rte_hash_reset
hash: add new functionality to store data in hash table
MAINTAINERS: claim responsability for hash library
doc: announce ABI change of librte_hash
doc: update hash documentation
MAINTAINERS | 1 +
app/test/test_hash.c | 189 +--
app/test/test_hash_perf.c | 906 ++++++-------
doc/guides/prog_guide/hash_lib.rst | 77 +-
doc/guides/rel_notes/abi.rst | 2 +
.../common/include/arch/ppc_64/rte_prefetch.h | 6 +-
.../common/include/arch/x86/rte_prefetch.h | 14 +-
.../common/include/generic/rte_prefetch.h | 8 +-
lib/librte_hash/Makefile | 8 +-
lib/librte_hash/rte_cuckoo_hash.c | 1394 ++++++++++++++++++++
lib/librte_hash/rte_hash.c | 471 -------
lib/librte_hash/rte_hash.h | 274 +++-
lib/librte_hash/rte_hash_version.map | 15 +
13 files changed, 2191 insertions(+), 1174 deletions(-)
create mode 100644 lib/librte_hash/rte_cuckoo_hash.c
delete mode 100644 lib/librte_hash/rte_hash.c
--
2.4.2
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation
@ 2015-06-25 14:35 28% ` Neil Horman
2015-06-26 13:00 4% ` Thomas Monjalon
1 sibling, 1 reply; 200+ results
From: Neil Horman @ 2015-06-25 14:35 UTC (permalink / raw)
To: dev
People have been asking for ways to use the ABI macros, heres some docs to
clarify their use. Included is:
* An overview of what ABI is
* Details of the ABI deprecation process
* Details of the versioning macros
* Examples of their use
* Details of how to use the ABI validator
Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
working on it. Much of the introductory material was gathered and cleaned up by
him
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: john.mcnamara@intel.com
CC: thomas.monjalon@6wind.com
Change notes:
v2)
* Fixed RST indentations and spelling errors
* Rebased to upstream to fix index.rst conflict
v3)
* Fixed in tact -> intact
* Added docs to address static linking
* Removed duplicate documentation from release notes
---
doc/guides/guidelines/index.rst | 1 +
doc/guides/guidelines/versioning.rst | 484 +++++++++++++++++++++++++++++++++++
doc/guides/rel_notes/abi.rst | 30 +--
3 files changed, 487 insertions(+), 28 deletions(-)
create mode 100644 doc/guides/guidelines/versioning.rst
diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
index 0ee9ab3..bfb9fa3 100644
--- a/doc/guides/guidelines/index.rst
+++ b/doc/guides/guidelines/index.rst
@@ -7,3 +7,4 @@ Guidelines
coding_style
design
+ versioning
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
new file mode 100644
index 0000000..da9eca0
--- /dev/null
+++ b/doc/guides/guidelines/versioning.rst
@@ -0,0 +1,484 @@
+Managing ABI updates
+====================
+
+Description
+-----------
+
+This document details some methods for handling ABI management in the DPDK.
+Note this document is not exhaustive, in that C library versioning is flexible
+allowing multiple methods to achieve various goals, but it will provide the user
+with some introductory methods
+
+General Guidelines
+------------------
+
+#. Whenever possible, ABI should be preserved
+#. The addition of symbols is generally not problematic
+#. The modification of symbols can generally be managed with versioning
+#. The removal of symbols generally is an ABI break and requires bumping of the
+ LIBABIVER macro
+
+What is an ABI
+--------------
+
+An ABI (Application Binary Interface) is the set of runtime interfaces exposed
+by a library. It is similar to an API (Application Programming Interface) but
+is the result of compilation. It is also effectively cloned when applications
+link to dynamic libraries. That is to say when an application is compiled to
+link against dynamic libraries, it is assumed that the ABI remains constant
+between the time the application is compiled/linked, and the time that it runs.
+Therefore, in the case of dynamic linking, it is critical that an ABI is
+preserved, or (when modified), done in such a way that the application is unable
+to behave improperly or in an unexpected fashion.
+
+The DPDK ABI policy
+-------------------
+
+ABI versions are set at the time of major release labeling, and the ABI may
+change multiple times, without warning, between the last release label and the
+HEAD label of the git tree.
+
+ABI versions, once released, are available until such time as their
+deprecation has been noted in the Release Notes for at least one major release
+cycle. For example consider the case where the ABI for DPDK 2.0 has been
+shipped and then a decision is made to modify it during the development of
+DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1
+release and the modification will be made available in the DPDK 2.2 release.
+
+ABI versions may be deprecated in whole or in part as needed by a given
+update.
+
+Some ABI changes may be too significant to reasonably maintain multiple
+versions. In those cases ABI's may be updated without backward compatibility
+being provided. The requirements for doing so are:
+
+#. At least 3 acknowledgments of the need to do so must be made on the
+ dpdk.org mailing list.
+
+#. A full deprecation cycle, as explained above, must be made to offer
+ downstream consumers sufficient warning of the change.
+
+#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
+ incorporated must be incremented in parallel with the ABI changes
+ themselves.
+
+Note that the above process for ABI deprecation should not be undertaken
+lightly. ABI stability is extremely important for downstream consumers of the
+DPDK, especially when distributed in shared object form. Every effort should
+be made to preserve the ABI whenever possible. The ABI should only be changed
+for significant reasons, such as performance enhancements. ABI breakage due to
+changes such as reorganizing public structure fields for aesthetic or
+readability purposes should be avoided.
+
+Examples of Deprecation Notices
+-------------------------------
+
+The following are some examples of ABI deprecation notices which would be
+added to the Release Notes:
+
+* The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0,
+ to be replaced with the inline function ``rte_foo()``.
+
+* The function ``rte_mbuf_grok()`` has been updated to include a new parameter
+ in version 2.0. Backwards compatibility will be maintained for this function
+ until the release of version 2.1
+
+* The members of ``struct rte_foo`` have been reorganized in release 2.0 for
+ performance reasons. Existing binary applications will have backwards
+ compatibility in release 2.0, while newly built binaries will need to
+ reference the new structure variant ``struct rte_foo2``. Compatibility will
+ be removed in release 2.2, and all applications will require updating and
+ rebuilding to the new structure at that time, which will be renamed to the
+ original ``struct rte_foo``.
+
+* Significant ABI changes are planned for the ``librte_dostuff`` library. The
+ upcoming release 2.0 will not contain these changes, but release 2.1 will,
+ and no backwards compatibility is planned due to the extensive nature of
+ these changes. Binaries using this library built prior to version 2.1 will
+ require updating and recompilation.
+
+Versioning Macros
+-----------------
+
+When a symbol is exported from a library to provide an API, it also provides a
+calling convention (ABI) that is embodied in its name, return type and
+arguments. Occasionally that function may need to change to accommodate new
+functionality or behavior. When that occurs, it is desirable to allow for
+backward compatibility for a time with older binaries that are dynamically
+linked to the DPDK.
+
+To support backward compatibility the ``lib/librte_compat/rte_compat.h``
+header file provides macros to use when updating exported functions. These
+macros are used in conjunction with the ``rte_<library>_version.map`` file for
+a given library to allow multiple versions of a symbol to exist in a shared
+library so that older binaries need not be immediately recompiled.
+
+The macros exported are:
+
+* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
+ unversioned symbol ``b`` to the internal function ``b_e``.
+
+
+* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
+ unversioned symbol ``b`` to the internal function ``b_e``.
+
+* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry instructing
+ the linker to bind references to symbol ``b`` to the internal symbol
+ ``b_e``.
+
+* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the fully
+qualified function ``p``, so that if a symbol becomes versioned, it can still be
+mapped back to the public symbol name.
+
+Examples of ABI Macro use
+-------------------------
+
+Updating a public API
+~~~~~~~~~~~~~~~~~~~~~
+
+Assume we have a function as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param)
+ {
+ ...
+ }
+
+
+Assume that struct rte_acl_ctx is a private structure, and that a developer
+wishes to enhance the acl api so that a debugging flag can be enabled on a
+per-context basis. This requires an addition to the structure (which, being
+private, is safe), but it also requires modifying the code as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param, int debug)
+ {
+ ...
+ }
+
+
+Note also that, being a public function, the header file prototype must also be
+changed, as must all the call sites, to reflect the new ABI footprint. We will
+maintain previous ABI versions that are accessible only to previously compiled
+binaries
+
+The addition of a parameter to the function is ABI breaking as the function is
+public, and existing application may use it in its current form. However, the
+compatibility macros in DPDK allow a developer to use symbol versioning so that
+multiple functions can be mapped to the same public symbol based on when an
+application was linked to it. To see how this is done, we start with the
+requisite libraries version map file. Initially the version map file for the
+acl library looks like this
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+This file needs to be modified as follows
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+
+ } DPDK_2.0;
+
+The addition of the new block tells the linker that a new version node is
+available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
+symbols from the DPDK_2.0 node. This list is directly translated into a list of
+exported symbols when DPDK is compiled as a shared library
+
+Next, we need to specify in the code which function map to the rte_acl_create
+symbol at which versions. First, at the site of the initial symbol definition,
+we need to update the function so that it is uniquely named, and not in conflict
+with the public symbol name
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param)
+ +rte_acl_create_v20(const struct rte_acl_param *param)
+ {
+ size_t sz;
+ struct rte_acl_ctx *ctx;
+ ...
+
+Note that the base name of the symbol was kept intact, as this is condusive to
+the macros used for versioning symbols. That is our next step, mapping this new
+symbol name to the initial symbol name at version node 2.0. Immediately after
+the function, we add this line of code
+
+.. code-block:: c
+
+ VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+Remembering to also add the rte_compat.h header to the requisite c file where
+these changes are being made. The above macro instructs the linker to create a
+new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
+builds, but now points to the above newly named function. We have now mapped
+the original rte_acl_create symbol to the original function (but with a new
+name)
+
+Next, we need to create the 2.1 version of the symbol. We create a new function
+name, with a different suffix, and implement it appropriately
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ rte_acl_create_v21(const struct rte_acl_param *param, int debug);
+ {
+ struct rte_acl_ctx *ctx = rte_acl_create_v20(param);
+
+ ctx->debug = debug;
+
+ return ctx;
+ }
+
+This code serves as our new API call. Its the same as our old call, but adds
+the new parameter in place. Next we need to map this function to the symbol
+``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call
+in the header file, adding the macro there to inform all including applications,
+that on re-link, the default rte_acl_create symbol should point to this
+function. Note that we could do this by simply naming the function above
+rte_acl_create, and the linker would chose the most recent version tag to apply
+in the version script, but we can also do this in the header file
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param);
+ +rte_acl_create(const struct rte_acl_param *param, int debug);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
+header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1
+version node to it. This method is more explicit and flexible than just
+re-implementing the exact symbol name, and allows for other features (such as
+linking to the old symbol version by default, when the new ABI is to be opt-in
+for a period.
+
+One last thing we need to do. Note that we've taken what was a public symbol,
+and duplicated it into two uniquely and differently named symbols. We've then
+mapped each of those back to the public symbol ``rte_acl_create`` with different
+version tags. This only applies to dynamic linking, as static linking has no
+notion of versioning. That leaves this code in a position of no longer having a
+symbol simply named ``rte_acl_create`` and a static build will fail on that
+missing symbol.
+
+To correct this, we can simply map a function of our choosing back to the public
+symbol in the static build with the ``MAP_STATIC_SYMBOL`` macro. Generally the
+assumption is that the most recent version of the symbol is the one you want to
+map. So, back in the C file where, immediately after ``rte_acl_create_v21`` is
+defined, we add this
+
+.. code-block:: c
+
+ struct rte_acl_create_v21(const struct rte_acl_param *param, int debug)
+ {
+ ...
+ }
+ MAP_STATIC_SYMBOL(struct rte_acl_create(const struct rte_acl_param *param, int debug), rte_acl_create_v21);
+
+That tells the compiler that, when building a static library, any calls to the
+symbol ``rte_acl_create`` should be linked to ``rte_acl_create_v21``
+
+That's it, on the next shared library rebuild, there will be two versions of
+rte_acl_create, an old DPDK_2.0 version, used by previously built applications,
+and a new DPDK_2.1 version, used by future built applications.
+
+
+Deprecating part of a public API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lets assume that you've done the above update, and after a few releases have
+passed you decide you would like to retire the old version of the function.
+After having gone through the ABI deprecation announcement process, removal is
+easy. Start by removing the symbol from the requisite version map file:
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ - rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+ } DPDK_2.0;
+
+
+Next remove the corresponding versioned export
+.. code-block:: c
+
+ -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+
+Note that the internal function definition could also be removed, but its used
+in our example by the newer version _v21, so we leave it in place. This is a
+coding style choice.
+
+Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
+indicate to applications doing dynamic linking that this is a later, and
+possibly incompatible library version:
+
+.. code-block:: c
+
+ -LIBABIVER := 1
+ +LIBABIVER := 2
+
+Deprecating an entire ABI version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+While removing a symbol from and ABI may be useful, it is often more practical
+to remove an entire version node at once. If a version node completely
+specifies an API, then removing part of it, typically makes it incomplete. In
+those cases it is better to remove the entire node
+
+To do this, start by modifying the version map file, such that all symbols from
+the node to be removed are merged into the next node in the map
+
+In the case of our map above, it would transform to look as follows
+
+.. code-block:: none
+
+ DPDK_2.1 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+Then any uses of BIND_DEFAULT_SYMBOL that pointed to the old node should be
+updated to point to the new version node in any header files for all affected
+symbols.
+
+.. code-block:: c
+
+ -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+Lastly, any VERSION_SYMBOL macros that point to the old version node should be
+removed, taking care to keep, where need old code in place to support newer
+versions of the symbol.
+
+Running the ABI Validator
+-------------------------
+
+The ``scripts`` directory in the DPDK source tree contains a utility program,
+``validate-abi.sh``, for validating the DPDK ABI based on the Linux `ABI
+Compliance Checker
+<http://ispras.linuxbase.org/index.php/ABI_compliance_checker>`_.
+
+This has a dependency on the ``abi-compliance-checker`` and ``and abi-dumper``
+utilities which can be installed via a package manager. For example::
+
+ sudo yum install abi-compliance-checker
+ sudo yum install abi-dumper
+
+The syntax of the ``validate-abi.sh`` utility is::
+
+ ./scripts/validate-abi.sh <TAG1> <TAG2> <TARGET>
+
+Where ``TAG1`` and ``TAG2`` are valid git tags on the local repo and target is
+the usual DPDK compilation target.
+
+For example to test the current committed HEAD against a previous release tag
+we could add a temporary tag and run the utility as follows::
+
+ git tag MY_TEMP_TAG
+ ./scripts/validate-abi.sh v2.0.0 MY_TEMP_TAG x86_64-native-linuxapp-gcc
+
+After the validation script completes (it can take a while since it need to
+compile both tags) it will create compatibility reports in the
+``./compat_report`` directory. Listed incompatibilities can be found as
+follows::
+
+ grep -lr Incompatible compat_reports/
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..4086198 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -1,33 +1,7 @@
ABI policy
==========
-ABI versions are set at the time of major release labeling, and ABI may change
-multiple times between the last labeling and the HEAD label of the git tree
-without warning.
-
-ABI versions, once released are available until such time as their
-deprecation has been noted here for at least one major release cycle, after it
-has been tagged. E.g. the ABI for DPDK 2.0 is shipped, and then the decision to
-remove it is made during the development of DPDK 2.1. The decision will be
-recorded here, shipped with the DPDK 2.1 release, and actually removed when DPDK
-2.2 ships.
-
-ABI versions may be deprecated in whole, or in part as needed by a given update.
-
-Some ABI changes may be too significant to reasonably maintain multiple
-versions of. In those events ABI's may be updated without backward
-compatibility provided. The requirements for doing so are:
-
-#. At least 3 acknowledgments of the need on the dpdk.org
-#. A full deprecation cycle must be made to offer downstream consumers sufficient warning of the change. E.g. if dpdk 2.0 is under development when the change is proposed, a deprecation notice must be added to this file, and released with dpdk 2.0. Then the change may be incorporated for dpdk 2.1
-#. The LIBABIVER variable in the makefile(s) where the ABI changes are incorporated must be incremented in parallel with the ABI changes themselves
-
-Note that the above process for ABI deprecation should not be undertaken
-lightly. ABI stability is extremely important for downstream consumers of the
-DPDK, especially when distributed in shared object form. Every effort should be
-made to preserve ABI whenever possible. For instance, reorganizing public
-structure field for aesthetic or readability purposes should be avoided as it will
-cause ABI breakage. Only significant (e.g. performance) reasons should be seen
-as cause to alter ABI.
+See the guidelines document for details of the ABI policy. ABI deprecation
+notices are to be posted here
Examples of Deprecation Notices
-------------------------------
--
2.1.0
^ permalink raw reply [relevance 28%]
* [dpdk-dev] [PATCH v4 2/9] eal: memzone allocated by malloc
2015-06-25 14:05 4% ` [dpdk-dev] [PATCH v4 0/9] Dynamic memzone Sergio Gonzalez Monroy
@ 2015-06-25 14:05 1% ` Sergio Gonzalez Monroy
2015-06-25 14:05 14% ` [dpdk-dev] [PATCH v4 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-25 14:05 UTC (permalink / raw)
To: dev
In the current memory hierarchy, memsegs are groups of physically
contiguous hugepages, memzones are slices of memsegs and malloc further
slices memzones into smaller memory chunks.
This patch modifies malloc so it partitions memsegs instead of memzones.
Thus memzones would call malloc internally for memory allocation while
maintaining its ABI.
It would be possible to free memzones and therefore any other structure
based on memzones, ie. mempools
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
lib/librte_eal/common/eal_common_memzone.c | 274 ++++++----------------
lib/librte_eal/common/include/rte_eal_memconfig.h | 2 +-
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/malloc_elem.c | 68 ++++--
lib/librte_eal/common/malloc_elem.h | 14 +-
lib/librte_eal/common/malloc_heap.c | 140 ++++++-----
lib/librte_eal/common/malloc_heap.h | 6 +-
lib/librte_eal/common/rte_malloc.c | 7 +-
8 files changed, 197 insertions(+), 317 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index aee184a..943012b 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -50,15 +50,15 @@
#include <rte_string_fns.h>
#include <rte_common.h>
+#include "malloc_heap.h"
+#include "malloc_elem.h"
#include "eal_private.h"
-/* internal copy of free memory segments */
-static struct rte_memseg *free_memseg = NULL;
-
static inline const struct rte_memzone *
memzone_lookup_thread_unsafe(const char *name)
{
const struct rte_mem_config *mcfg;
+ const struct rte_memzone *mz;
unsigned i = 0;
/* get pointer to global configuration */
@@ -68,8 +68,9 @@ memzone_lookup_thread_unsafe(const char *name)
* the algorithm is not optimal (linear), but there are few
* zones and this function should be called at init only
*/
- for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) {
- if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE))
+ for (i = 0; i < RTE_MAX_MEMZONE; i++) {
+ mz = &mcfg->memzone[i];
+ if (mz->addr != NULL && !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE))
return &mcfg->memzone[i];
}
@@ -88,39 +89,45 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id,
len, socket_id, flags, RTE_CACHE_LINE_SIZE);
}
-/*
- * Helper function for memzone_reserve_aligned_thread_unsafe().
- * Calculate address offset from the start of the segment.
- * Align offset in that way that it satisfy istart alignmnet and
- * buffer of the requested length would not cross specified boundary.
- */
-static inline phys_addr_t
-align_phys_boundary(const struct rte_memseg *ms, size_t len, size_t align,
- size_t bound)
+/* Find the heap with the greatest free block size */
+static void
+find_heap_max_free_elem(int *s, size_t *len, unsigned align)
{
- phys_addr_t addr_offset, bmask, end, start;
- size_t step;
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- step = RTE_MAX(align, bound);
- bmask = ~((phys_addr_t)bound - 1);
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate offset to closest alignment */
- start = RTE_ALIGN_CEIL(ms->phys_addr, align);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size > *len) {
+ *len = stats.greatest_free_size;
+ *s = i;
+ }
+ }
+ *len -= (MALLOC_ELEM_OVERHEAD + align);
+}
- while (addr_offset + len < ms->len) {
+/* Find a heap that can allocate the requested size */
+static void
+find_heap_suitable(int *s, size_t len, unsigned align)
+{
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- /* check, do we meet boundary condition */
- end = start + len - (len != 0);
- if ((start & bmask) == (end & bmask))
- break;
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate next offset */
- start = RTE_ALIGN_CEIL(start + 1, step);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size >= len + MALLOC_ELEM_OVERHEAD + align) {
+ *s = i;
+ break;
+ }
}
-
- return addr_offset;
}
static const struct rte_memzone *
@@ -128,13 +135,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
int socket_id, unsigned flags, unsigned align, unsigned bound)
{
struct rte_mem_config *mcfg;
- unsigned i = 0;
- int memseg_idx = -1;
- uint64_t addr_offset, seg_offset = 0;
size_t requested_len;
- size_t memseg_len = 0;
- phys_addr_t memseg_physaddr;
- void *memseg_addr;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
@@ -166,7 +167,6 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
if (align < RTE_CACHE_LINE_SIZE)
align = RTE_CACHE_LINE_SIZE;
-
/* align length on cache boundary. Check for overflow before doing so */
if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) {
rte_errno = EINVAL; /* requested size too big */
@@ -180,129 +180,50 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len);
/* check that boundary condition is valid */
- if (bound != 0 &&
- (requested_len > bound || !rte_is_power_of_2(bound))) {
+ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) {
rte_errno = EINVAL;
return NULL;
}
- /* find the smallest segment matching requirements */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- /* last segment */
- if (free_memseg[i].addr == NULL)
- break;
+ if (len == 0) {
+ if (bound != 0)
+ requested_len = bound;
+ else
+ requested_len = 0;
+ }
- /* empty segment, skip it */
- if (free_memseg[i].len == 0)
- continue;
-
- /* bad socket ID */
- if (socket_id != SOCKET_ID_ANY &&
- free_memseg[i].socket_id != SOCKET_ID_ANY &&
- socket_id != free_memseg[i].socket_id)
- continue;
-
- /*
- * calculate offset to closest alignment that
- * meets boundary conditions.
- */
- addr_offset = align_phys_boundary(free_memseg + i,
- requested_len, align, bound);
-
- /* check len */
- if ((requested_len + addr_offset) > free_memseg[i].len)
- continue;
-
- /* check flags for hugepage sizes */
- if ((flags & RTE_MEMZONE_2MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_1G)
- continue;
- if ((flags & RTE_MEMZONE_1GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_2M)
- continue;
- if ((flags & RTE_MEMZONE_16MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16G)
- continue;
- if ((flags & RTE_MEMZONE_16GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16M)
- continue;
-
- /* this segment is the best until now */
- if (memseg_idx == -1) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- /* find the biggest contiguous zone */
- else if (len == 0) {
- if (free_memseg[i].len > memseg_len) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- }
- /*
- * find the smallest (we already checked that current
- * zone length is > len
- */
- else if (free_memseg[i].len + align < memseg_len ||
- (free_memseg[i].len <= memseg_len + align &&
- addr_offset < seg_offset)) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
+ if (socket_id == SOCKET_ID_ANY) {
+ if (requested_len == 0)
+ find_heap_max_free_elem(&socket_id, &requested_len, align);
+ else
+ find_heap_suitable(&socket_id, requested_len, align);
+
+ if (socket_id == SOCKET_ID_ANY) {
+ rte_errno = ENOMEM;
+ return NULL;
}
}
- /* no segment found */
- if (memseg_idx == -1) {
- /*
- * If RTE_MEMZONE_SIZE_HINT_ONLY flag is specified,
- * try allocating again without the size parameter otherwise -fail.
- */
- if ((flags & RTE_MEMZONE_SIZE_HINT_ONLY) &&
- ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB)
- || (flags & RTE_MEMZONE_16MB) || (flags & RTE_MEMZONE_16GB)))
- return memzone_reserve_aligned_thread_unsafe(name,
- len, socket_id, 0, align, bound);
-
+ /* allocate memory on heap */
+ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket_id], NULL,
+ requested_len, flags, align, bound);
+ if (mz_addr == NULL) {
rte_errno = ENOMEM;
return NULL;
}
- /* save aligned physical and virtual addresses */
- memseg_physaddr = free_memseg[memseg_idx].phys_addr + seg_offset;
- memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr,
- (uintptr_t) seg_offset);
-
- /* if we are looking for a biggest memzone */
- if (len == 0) {
- if (bound == 0)
- requested_len = memseg_len - seg_offset;
- else
- requested_len = RTE_ALIGN_CEIL(memseg_physaddr + 1,
- bound) - memseg_physaddr;
- }
-
- /* set length to correct value */
- len = (size_t)seg_offset + requested_len;
-
- /* update our internal state */
- free_memseg[memseg_idx].len -= len;
- free_memseg[memseg_idx].phys_addr += len;
- free_memseg[memseg_idx].addr =
- (char *)free_memseg[memseg_idx].addr + len;
+ const struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
/* fill the zone in config */
struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++];
snprintf(mz->name, sizeof(mz->name), "%s", name);
- mz->phys_addr = memseg_physaddr;
- mz->addr = memseg_addr;
- mz->len = requested_len;
- mz->hugepage_sz = free_memseg[memseg_idx].hugepage_sz;
- mz->socket_id = free_memseg[memseg_idx].socket_id;
+ mz->phys_addr = rte_malloc_virt2phy(mz_addr);
+ mz->addr = mz_addr;
+ mz->len = (requested_len == 0 ? elem->size : requested_len);
+ mz->hugepage_sz = elem->ms->hugepage_sz;
+ mz->socket_id = elem->ms->socket_id;
mz->flags = 0;
- mz->memseg_id = memseg_idx;
+ mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg;
return mz;
}
@@ -419,45 +340,6 @@ rte_memzone_dump(FILE *f)
}
/*
- * called by init: modify the free memseg list to have cache-aligned
- * addresses and cache-aligned lengths
- */
-static int
-memseg_sanitize(struct rte_memseg *memseg)
-{
- unsigned phys_align;
- unsigned virt_align;
- unsigned off;
-
- phys_align = memseg->phys_addr & RTE_CACHE_LINE_MASK;
- virt_align = (unsigned long)memseg->addr & RTE_CACHE_LINE_MASK;
-
- /*
- * sanity check: phys_addr and addr must have the same
- * alignment
- */
- if (phys_align != virt_align)
- return -1;
-
- /* memseg is really too small, don't bother with it */
- if (memseg->len < (2 * RTE_CACHE_LINE_SIZE)) {
- memseg->len = 0;
- return 0;
- }
-
- /* align start address */
- off = (RTE_CACHE_LINE_SIZE - phys_align) & RTE_CACHE_LINE_MASK;
- memseg->phys_addr += off;
- memseg->addr = (char *)memseg->addr + off;
- memseg->len -= off;
-
- /* align end address */
- memseg->len &= ~((uint64_t)RTE_CACHE_LINE_MASK);
-
- return 0;
-}
-
-/*
* Init the memzone subsystem
*/
int
@@ -465,14 +347,10 @@ rte_eal_memzone_init(void)
{
struct rte_mem_config *mcfg;
const struct rte_memseg *memseg;
- unsigned i = 0;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
- /* mirror the runtime memsegs from config */
- free_memseg = mcfg->free_memseg;
-
/* secondary processes don't need to initialise anything */
if (rte_eal_process_type() == RTE_PROC_SECONDARY)
return 0;
@@ -485,33 +363,13 @@ rte_eal_memzone_init(void)
rte_rwlock_write_lock(&mcfg->mlock);
- /* fill in uninitialized free_memsegs */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (memseg[i].addr == NULL)
- break;
- if (free_memseg[i].addr != NULL)
- continue;
- memcpy(&free_memseg[i], &memseg[i], sizeof(struct rte_memseg));
- }
-
- /* make all zones cache-aligned */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (free_memseg[i].addr == NULL)
- break;
- if (memseg_sanitize(&free_memseg[i]) < 0) {
- RTE_LOG(ERR, EAL, "%s(): Sanity check failed\n", __func__);
- rte_rwlock_write_unlock(&mcfg->mlock);
- return -1;
- }
- }
-
/* delete all zones */
mcfg->memzone_idx = 0;
memset(mcfg->memzone, 0, sizeof(mcfg->memzone));
rte_rwlock_write_unlock(&mcfg->mlock);
- return 0;
+ return rte_eal_malloc_heap_init();
}
/* Walk all reserved memory zones */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 34f5abc..055212a 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -73,7 +73,7 @@ struct rte_mem_config {
struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */
struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */
- /* Runtime Physmem descriptors. */
+ /* Runtime Physmem descriptors - NOT USED */
struct rte_memseg free_memseg[RTE_MAX_MEMSEG];
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h
index 716216f..b270356 100644
--- a/lib/librte_eal/common/include/rte_malloc_heap.h
+++ b/lib/librte_eal/common/include/rte_malloc_heap.h
@@ -40,7 +40,7 @@
#include <rte_memory.h>
/* Number of free lists per heap, grouped by size. */
-#define RTE_HEAP_NUM_FREELISTS 5
+#define RTE_HEAP_NUM_FREELISTS 13
/**
* Structure to hold malloc heap
@@ -48,7 +48,6 @@
struct malloc_heap {
rte_spinlock_t lock;
LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS];
- unsigned mz_count;
unsigned alloc_count;
size_t total_size;
} __rte_cache_aligned;
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index a5e1248..b54ee33 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -37,7 +37,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include <rte_per_lcore.h>
@@ -56,10 +55,10 @@
*/
void
malloc_elem_init(struct malloc_elem *elem,
- struct malloc_heap *heap, const struct rte_memzone *mz, size_t size)
+ struct malloc_heap *heap, const struct rte_memseg *ms, size_t size)
{
elem->heap = heap;
- elem->mz = mz;
+ elem->ms = ms;
elem->prev = NULL;
memset(&elem->free_list, 0, sizeof(elem->free_list));
elem->state = ELEM_FREE;
@@ -70,12 +69,12 @@ malloc_elem_init(struct malloc_elem *elem,
}
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
{
- malloc_elem_init(elem, prev->heap, prev->mz, 0);
+ malloc_elem_init(elem, prev->heap, prev->ms, 0);
elem->prev = prev;
elem->state = ELEM_BUSY; /* mark busy so its never merged */
}
@@ -86,12 +85,24 @@ malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
* fit, return NULL.
*/
static void *
-elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
+elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- const uintptr_t end_pt = (uintptr_t)elem +
+ const size_t bmask = ~(bound - 1);
+ uintptr_t end_pt = (uintptr_t)elem +
elem->size - MALLOC_ELEM_TRAILER_LEN;
- const uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
- const uintptr_t new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
+ uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ uintptr_t new_elem_start;
+
+ /* check boundary */
+ if ((new_data_start & bmask) != ((end_pt - 1) & bmask)) {
+ end_pt = RTE_ALIGN_FLOOR(end_pt, bound);
+ new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ if (((end_pt - 1) & bmask) != (new_data_start & bmask))
+ return NULL;
+ }
+
+ new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
/* if the new start point is before the exist start, it won't fit */
return (new_elem_start < (uintptr_t)elem) ? NULL : (void *)new_elem_start;
@@ -102,9 +113,10 @@ elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
* alignment request from the current element
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- return elem_start_pt(elem, size, align) != NULL;
+ return elem_start_pt(elem, size, align, bound) != NULL;
}
/*
@@ -115,10 +127,10 @@ static void
split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)
{
struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size);
- const unsigned old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
- const unsigned new_elem_size = elem->size - old_elem_size;
+ const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
+ const size_t new_elem_size = elem->size - old_elem_size;
- malloc_elem_init(split_pt, elem->heap, elem->mz, new_elem_size);
+ malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size);
split_pt->prev = elem;
next_elem->prev = split_pt;
elem->size = old_elem_size;
@@ -168,8 +180,9 @@ malloc_elem_free_list_index(size_t size)
void
malloc_elem_free_list_insert(struct malloc_elem *elem)
{
- size_t idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
+ size_t idx;
+ idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
elem->state = ELEM_FREE;
LIST_INSERT_HEAD(&elem->heap->free_head[idx], elem, free_list);
}
@@ -190,12 +203,26 @@ elem_free_list_remove(struct malloc_elem *elem)
* is not done here, as it's done there previously.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- struct malloc_elem *new_elem = elem_start_pt(elem, size, align);
- const unsigned old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound);
+ const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ const size_t trailer_size = elem->size - old_elem_size - size -
+ MALLOC_ELEM_OVERHEAD;
+
+ elem_free_list_remove(elem);
- if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE){
+ if (trailer_size > MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* split it, too much free space after elem */
+ struct malloc_elem *new_free_elem =
+ RTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD);
+
+ split_elem(elem, new_free_elem);
+ malloc_elem_free_list_insert(new_free_elem);
+ }
+
+ if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
/* don't split it, pad the element instead */
elem->state = ELEM_BUSY;
elem->pad = old_elem_size;
@@ -208,8 +235,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
new_elem->size = elem->size - elem->pad;
set_header(new_elem);
}
- /* remove element from free list */
- elem_free_list_remove(elem);
return new_elem;
}
@@ -219,7 +244,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
* Re-insert original element, in case its new size makes it
* belong on a different list.
*/
- elem_free_list_remove(elem);
split_elem(elem, new_elem);
new_elem->state = ELEM_BUSY;
malloc_elem_free_list_insert(elem);
diff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h
index 9790b1a..e05d2ea 100644
--- a/lib/librte_eal/common/malloc_elem.h
+++ b/lib/librte_eal/common/malloc_elem.h
@@ -47,9 +47,9 @@ enum elem_state {
struct malloc_elem {
struct malloc_heap *heap;
- struct malloc_elem *volatile prev; /* points to prev elem in memzone */
+ struct malloc_elem *volatile prev; /* points to prev elem in memseg */
LIST_ENTRY(malloc_elem) free_list; /* list of free elements in heap */
- const struct rte_memzone *mz;
+ const struct rte_memseg *ms;
volatile enum elem_state state;
uint32_t pad;
size_t size;
@@ -136,11 +136,11 @@ malloc_elem_from_data(const void *data)
void
malloc_elem_init(struct malloc_elem *elem,
struct malloc_heap *heap,
- const struct rte_memzone *mz,
+ const struct rte_memseg *ms,
size_t size);
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem,
@@ -151,14 +151,16 @@ malloc_elem_mkend(struct malloc_elem *elem,
* of the requested size and with the requested alignment
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* reserve a block of data in an existing malloc_elem. If the malloc_elem
* is much larger than the data block requested, we split the element in two.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_alloc(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* free a malloc_elem block by adding it to the free list. If the
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 8861d27..f5fff96 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -39,7 +39,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_launch.h>
@@ -54,123 +53,104 @@
#include "malloc_elem.h"
#include "malloc_heap.h"
-/* since the memzone size starts with a digit, it will appear unquoted in
- * rte_config.h, so quote it so it can be passed to rte_str_to_size */
-#define MALLOC_MEMZONE_SIZE RTE_STR(RTE_MALLOC_MEMZONE_SIZE)
-
-/*
- * returns the configuration setting for the memzone size as a size_t value
- */
-static inline size_t
-get_malloc_memzone_size(void)
+static unsigned
+check_hugepage_sz(unsigned flags, size_t hugepage_sz)
{
- return rte_str_to_size(MALLOC_MEMZONE_SIZE);
+ unsigned ret = 1;
+
+ if ((flags & RTE_MEMZONE_2MB) && hugepage_sz == RTE_PGSIZE_1G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_1GB) && hugepage_sz == RTE_PGSIZE_2M)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16MB) && hugepage_sz == RTE_PGSIZE_16G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16GB) && hugepage_sz == RTE_PGSIZE_16M)
+ ret = 0;
+
+ return ret;
}
/*
- * reserve an extra memory zone and make it available for use by a particular
- * heap. This reserves the zone and sets a dummy malloc_elem header at the end
+ * Expand the heap with a memseg.
+ * This reserves the zone and sets a dummy malloc_elem header at the end
* to prevent overflow. The rest of the zone is added to free list as a single
* large free block
*/
-static int
-malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
+static void
+malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)
{
- const unsigned mz_flags = 0;
- const size_t block_size = get_malloc_memzone_size();
- /* ensure the data we want to allocate will fit in the memzone */
- const size_t min_size = size + align + MALLOC_ELEM_OVERHEAD * 2;
- const struct rte_memzone *mz = NULL;
- struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
- unsigned numa_socket = heap - mcfg->malloc_heaps;
-
- size_t mz_size = min_size;
- if (mz_size < block_size)
- mz_size = block_size;
-
- char mz_name[RTE_MEMZONE_NAMESIZE];
- snprintf(mz_name, sizeof(mz_name), "MALLOC_S%u_HEAP_%u",
- numa_socket, heap->mz_count++);
-
- /* try getting a block. if we fail and we don't need as big a block
- * as given in the config, we can shrink our request and try again
- */
- do {
- mz = rte_memzone_reserve(mz_name, mz_size, numa_socket,
- mz_flags);
- if (mz == NULL)
- mz_size /= 2;
- } while (mz == NULL && mz_size > min_size);
- if (mz == NULL)
- return -1;
-
/* allocate the memory block headers, one at end, one at start */
- struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
- struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
- mz_size - MALLOC_ELEM_OVERHEAD);
+ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr;
+ struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr,
+ ms->len - MALLOC_ELEM_OVERHEAD);
end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);
+ const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- malloc_elem_init(start_elem, heap, mz, elem_size);
+ malloc_elem_init(start_elem, heap, ms, elem_size);
malloc_elem_mkend(end_elem, start_elem);
malloc_elem_free_list_insert(start_elem);
- /* increase heap total size by size of new memzone */
- heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
- return 0;
+ heap->total_size += elem_size;
}
/*
* Iterates through the freelist for a heap to find a free element
* which can store data of the required size and with the requested alignment.
+ * If size is 0, find the biggest available elem.
* Returns null on failure, or pointer to element on success.
*/
static struct malloc_elem *
-find_suitable_element(struct malloc_heap *heap, size_t size, unsigned align)
+find_suitable_element(struct malloc_heap *heap, size_t size,
+ unsigned flags, size_t align, size_t bound)
{
size_t idx;
- struct malloc_elem *elem;
+ struct malloc_elem *elem, *alt_elem = NULL;
for (idx = malloc_elem_free_list_index(size);
- idx < RTE_HEAP_NUM_FREELISTS; idx++)
- {
+ idx < RTE_HEAP_NUM_FREELISTS; idx++) {
for (elem = LIST_FIRST(&heap->free_head[idx]);
- !!elem; elem = LIST_NEXT(elem, free_list))
- {
- if (malloc_elem_can_hold(elem, size, align))
- return elem;
+ !!elem; elem = LIST_NEXT(elem, free_list)) {
+ if (malloc_elem_can_hold(elem, size, align, bound)) {
+ if (check_hugepage_sz(flags, elem->ms->hugepage_sz))
+ return elem;
+ alt_elem = elem;
+ }
}
}
+
+ if ((alt_elem != NULL) && (flags & RTE_MEMZONE_SIZE_HINT_ONLY))
+ return alt_elem;
+
return NULL;
}
/*
- * Main function called by malloc to allocate a block of memory from the
- * heap. It locks the free list, scans it, and adds a new memzone if the
- * scan fails. Once the new memzone is added, it re-scans and should return
+ * Main function to allocate a block of memory from the heap.
+ * It locks the free list, scans it, and adds a new memseg if the
+ * scan fails. Once the new memseg is added, it re-scans and should return
* the new element after releasing the lock.
*/
void *
malloc_heap_alloc(struct malloc_heap *heap,
- const char *type __attribute__((unused)), size_t size, unsigned align)
+ const char *type __attribute__((unused)), size_t size, unsigned flags,
+ size_t align, size_t bound)
{
+ struct malloc_elem *elem;
+
size = RTE_CACHE_LINE_ROUNDUP(size);
align = RTE_CACHE_LINE_ROUNDUP(align);
+
rte_spinlock_lock(&heap->lock);
- struct malloc_elem *elem = find_suitable_element(heap, size, align);
- if (elem == NULL){
- if ((malloc_heap_add_memzone(heap, size, align)) == 0)
- elem = find_suitable_element(heap, size, align);
- }
- if (elem != NULL){
- elem = malloc_elem_alloc(elem, size, align);
+ elem = find_suitable_element(heap, size, flags, align, bound);
+ if (elem != NULL) {
+ elem = malloc_elem_alloc(elem, size, align, bound);
/* increase heap's count of allocated elements */
heap->alloc_count++;
}
rte_spinlock_unlock(&heap->lock);
- return elem == NULL ? NULL : (void *)(&elem[1]);
+ return elem == NULL ? NULL : (void *)(&elem[1]);
}
/*
@@ -206,3 +186,21 @@ malloc_heap_get_stats(const struct malloc_heap *heap,
socket_stats->alloc_count = heap->alloc_count;
return 0;
}
+
+int
+rte_eal_malloc_heap_init(void)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ unsigned ms_cnt;
+ struct rte_memseg *ms;
+
+ if (mcfg == NULL)
+ return -1;
+
+ for (ms = &mcfg->memseg[0], ms_cnt = 0;
+ (ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0);
+ ms_cnt++, ms++)
+ malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms);
+
+ return 0;
+}
diff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h
index a47136d..3ccbef0 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -53,15 +53,15 @@ malloc_get_numa_socket(void)
}
void *
-malloc_heap_alloc(struct malloc_heap *heap, const char *type,
- size_t size, unsigned align);
+malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size,
+ unsigned flags, size_t align, size_t bound);
int
malloc_heap_get_stats(const struct malloc_heap *heap,
struct rte_malloc_socket_stats *socket_stats);
int
-rte_eal_heap_memzone_init(void);
+rte_eal_malloc_heap_init(void);
#ifdef __cplusplus
}
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index c313a57..54c2bd8 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -39,7 +39,6 @@
#include <rte_memcpy.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_branch_prediction.h>
@@ -87,7 +86,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
return NULL;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL || socket_arg != SOCKET_ID_ANY)
return ret;
@@ -98,7 +97,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
continue;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL)
return ret;
}
@@ -256,5 +255,5 @@ rte_malloc_virt2phy(const void *addr)
const struct malloc_elem *elem = malloc_elem_from_data(addr);
if (elem == NULL)
return 0;
- return elem->mz->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->mz->addr);
+ return elem->ms->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->ms->addr);
}
--
1.9.3
^ permalink raw reply [relevance 1%]
* [dpdk-dev] [PATCH v4 8/9] doc: announce ABI change of librte_malloc
2015-06-25 14:05 4% ` [dpdk-dev] [PATCH v4 0/9] Dynamic memzone Sergio Gonzalez Monroy
2015-06-25 14:05 1% ` [dpdk-dev] [PATCH v4 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
@ 2015-06-25 14:05 14% ` Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-25 14:05 UTC (permalink / raw)
To: dev
Announce the creation of dummy malloc library for 2.1 and removal of
such library, now integrated in librte_eal, for 2.2 release.
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
doc/guides/rel_notes/abi.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..2aaf900 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,4 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* librte_malloc library has been integrated into librte_eal. The 2.1 release creates a dummy/empty malloc library to fulfill binaries with dynamic linking dependencies on librte_malloc.so. Such dummy library will not be created from release 2.2 so binaries will need to be rebuilt.
--
1.9.3
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v4 0/9] Dynamic memzone
2015-06-19 17:21 4% ` [dpdk-dev] [PATCH v3 0/9] Dynamic memzone Sergio Gonzalez Monroy
@ 2015-06-25 14:05 4% ` Sergio Gonzalez Monroy
2015-06-25 14:05 1% ` [dpdk-dev] [PATCH v4 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-25 14:05 14% ` [dpdk-dev] [PATCH v4 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-26 11:32 4% ` [dpdk-dev] [PATCH v5 0/9] Dynamic memzones Sergio Gonzalez Monroy
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
3 siblings, 2 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-25 14:05 UTC (permalink / raw)
To: dev
Current implemetation allows reserving/creating memzones but not the opposite
(unreserve/free). This affects mempools and other memzone based objects.
>From my point of view, implementing free functionality for memzones would look
like malloc over memsegs.
Thus, this approach moves malloc inside eal (which in turn removes a circular
dependency), where malloc heaps are composed of memsegs.
We keep both malloc and memzone APIs as they are, but memzones allocate its
memory by calling malloc_heap_alloc.
Some extra functionality is required in malloc to allow for boundary constrained
memory requests.
In summary, currently malloc is based on memzones, and with this approach
memzones are based on malloc.
v4:
- rebase and fix couple of merge issues
v3:
- Create dummy librte_malloc
- Add deprecation notice
- Rework some of the code
- Doc update
- checkpatch
v2:
- New rte_memzone_free
- Support memzone len = 0
- Add all available memsegs to malloc heap at init
- Update memzone/malloc unit tests
Sergio Gonzalez Monroy (9):
eal: move librte_malloc to eal/common
eal: memzone allocated by malloc
app/test: update malloc/memzone unit tests
config: remove CONFIG_RTE_MALLOC_MEMZONE_SIZE
eal: remove free_memseg and references to it
eal: new rte_memzone_free
app/test: update unit test with rte_memzone_free
doc: announce ABI change of librte_malloc
doc: update malloc documentation
MAINTAINERS | 9 +-
app/test/test_malloc.c | 86 -----
app/test/test_memzone.c | 441 +++-------------------
config/common_bsdapp | 8 +-
config/common_linuxapp | 8 +-
doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++++++++-
doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 80952 bytes
doc/guides/prog_guide/index.rst | 1 -
doc/guides/prog_guide/malloc_lib.rst | 233 ------------
doc/guides/prog_guide/overview.rst | 11 +-
doc/guides/rel_notes/abi.rst | 1 +
drivers/net/af_packet/Makefile | 1 -
drivers/net/bonding/Makefile | 1 -
drivers/net/e1000/Makefile | 2 +-
drivers/net/enic/Makefile | 2 +-
drivers/net/fm10k/Makefile | 2 +-
drivers/net/i40e/Makefile | 2 +-
drivers/net/ixgbe/Makefile | 2 +-
drivers/net/mlx4/Makefile | 1 -
drivers/net/null/Makefile | 1 -
drivers/net/pcap/Makefile | 1 -
drivers/net/virtio/Makefile | 2 +-
drivers/net/vmxnet3/Makefile | 2 +-
drivers/net/xenvirt/Makefile | 2 +-
lib/Makefile | 2 +-
lib/librte_acl/Makefile | 2 +-
lib/librte_eal/bsdapp/eal/Makefile | 4 +-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 19 +
lib/librte_eal/common/Makefile | 1 +
lib/librte_eal/common/eal_common_memzone.c | 329 ++++++----------
lib/librte_eal/common/include/rte_eal_memconfig.h | 5 +-
lib/librte_eal/common/include/rte_malloc.h | 342 +++++++++++++++++
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/include/rte_memzone.h | 11 +
lib/librte_eal/common/malloc_elem.c | 344 +++++++++++++++++
lib/librte_eal/common/malloc_elem.h | 192 ++++++++++
lib/librte_eal/common/malloc_heap.c | 206 ++++++++++
lib/librte_eal/common/malloc_heap.h | 70 ++++
lib/librte_eal/common/rte_malloc.c | 259 +++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 4 +-
lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 +-
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 19 +
lib/librte_hash/Makefile | 2 +-
lib/librte_lpm/Makefile | 2 +-
lib/librte_malloc/Makefile | 6 +-
lib/librte_malloc/malloc_elem.c | 320 ----------------
lib/librte_malloc/malloc_elem.h | 190 ----------
lib/librte_malloc/malloc_heap.c | 208 ----------
lib/librte_malloc/malloc_heap.h | 70 ----
lib/librte_malloc/rte_malloc.c | 228 +----------
lib/librte_malloc/rte_malloc.h | 342 -----------------
lib/librte_malloc/rte_malloc_version.map | 16 -
lib/librte_mempool/Makefile | 2 -
lib/librte_port/Makefile | 1 -
lib/librte_ring/Makefile | 3 +-
lib/librte_table/Makefile | 1 -
56 files changed, 1897 insertions(+), 2362 deletions(-)
delete mode 100644 doc/guides/prog_guide/malloc_lib.rst
create mode 100644 lib/librte_eal/common/include/rte_malloc.h
create mode 100644 lib/librte_eal/common/malloc_elem.c
create mode 100644 lib/librte_eal/common/malloc_elem.h
create mode 100644 lib/librte_eal/common/malloc_heap.c
create mode 100644 lib/librte_eal/common/malloc_heap.h
create mode 100644 lib/librte_eal/common/rte_malloc.c
delete mode 100644 lib/librte_malloc/malloc_elem.c
delete mode 100644 lib/librte_malloc/malloc_elem.h
delete mode 100644 lib/librte_malloc/malloc_heap.c
delete mode 100644 lib/librte_malloc/malloc_heap.h
delete mode 100644 lib/librte_malloc/rte_malloc.h
--
1.9.3
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-25 11:35 9% ` Neil Horman
@ 2015-06-25 13:22 7% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-06-25 13:22 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-25 07:35, Neil Horman:
> On Wed, Jun 24, 2015 at 11:09:29PM +0200, Thomas Monjalon wrote:
> > 2015-06-24 14:34, Neil Horman:
> > > +Some ABI changes may be too significant to reasonably maintain multiple
> > > +versions. In those cases ABI's may be updated without backward compatibility
> > > +being provided. The requirements for doing so are:
> > > +
> > > +#. At least 3 acknowledgments of the need to do so must be made on the
> > > + dpdk.org mailing list.
> > > +
> > > +#. A full deprecation cycle, as explained above, must be made to offer
> > > + downstream consumers sufficient warning of the change.
> > > +
> > > +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
> > > + incorporated must be incremented in parallel with the ABI changes
> > > + themselves.
> >
> > The proposal was to provide the old and the new ABI in the same source code
> > during the deprecation cycle. The old ABI would be the default and people
> > can build the new one by enabling the NEXT_ABI config option.
> > So the migration to the new ABI is smoother.
>
> Yes....I'm not sure what you're saying here. The ABI doesn't 'Change' until the
> old ABI is removed (i.e. old applications are forced to adopt a new ABI), and so
> LIBABIVER has to be updated in parallel with that removal
I'm referring to previous threads suggesting a NEXT_ABI build option to be able
to build the old (default) ABI or the next one.
So the LIBABIVER and .map file would depend of enabling NEXT_ABI or not:
http://dpdk.org/ml/archives/dev/2015-June/019147.html
http://dpdk.org/ml/archives/dev/2015-June/019784.html
http://dpdk.org/ml/archives/dev/2015-June/019810.html
> > [...]
> > > +The macros exported are:
> > > +
> > > +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> > > + unversioned symbol ``b`` to the internal function ``b_e``.
> >
> > The definition is the same as BASE_SYMBOL.
> >
> No, they're different. VERSION_SYMBOL is defined as:
> VERSION_SYMBOL(b, e, n) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b) "@DPDK_" RTE_STR(n))
>
> while BASE_SYMBOL is
> #define BASE_SYMBOL(b, e) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b)"@")
Yes. I mean the comments are the same, so don't reflect the difference.
> > [...]
> > > + DPDK_2.0 {
> > > + global:
> > > +
> > > + rte_acl_add_rules;
> > > + rte_acl_build;
> > > + rte_acl_classify;
> > > + rte_acl_classify_alg;
> > > + rte_acl_classify_scalar;
> > > + rte_acl_create;
> >
> > So it's declared twice, right?
> > I think it should be explicit.
> >
> Yes, its listed once for each version node, so 2 delcarations. I thought that
> was made explicit by the use of the code block. What else would you like to
> see?
I think you should say it explicitly in the comment below the block.
> > > + rte_acl_dump;
> > > + rte_acl_find_existing;
> > > + rte_acl_free;
> > > + rte_acl_ipv4vlan_add_rules;
> > > + rte_acl_ipv4vlan_build;
> > > + rte_acl_list_dump;
> > > + rte_acl_reset;
> > > + rte_acl_reset_rules;
> > > + rte_acl_set_ctx_classify;
> > > +
> > > + local: *;
> > > + };
> > > +
> > > + DPDK_2.1 {
> > > + global:
> > > + rte_acl_create;
> > > +
> > > + } DPDK_2.0;
> > [...]
> > > +the macros used for versioning symbols. That is our next step, mapping this new
> > > +symbol name to the initial symbol name at version node 2.0. Immediately after
> > > +the function, we add this line of code
> > > +
> > > +.. code-block:: c
> > > +
> > > + VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
> >
> > Can it be declared before the function?
> >
> Strictly speaking yes, though its a bit odd from a sylistic point to declare
> versioned aliases for a symbol prior to defining the symbol itself (its like a
> forward declaration)
It allows to declare it near the function header.
> > When do we need to use BASE_SYMBOL?
> >
> For our purposes you currently don't, because there are no unversioned symbols
> in DPDK (since we use a map file). I've just included it here for completeness
> in the header file should it ever be needed in the future.
If it can be useful, please integrate a note to explain when it should be used.
> > [...]
> > > +This code serves as our new API call. Its the same as our old call, but adds
> > > +the new parameter in place. Next we need to map this function to the symbol
> > > +``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call
> > > +in the header file, adding the macro there to inform all including applications,
> > > +that on re-link, the default rte_acl_create symbol should point to this
> > > +function. Note that we could do this by simply naming the function above
> > > +rte_acl_create, and the linker would chose the most recent version tag to apply
> > > +in the version script, but we can also do this in the header file
> > > +
> > > +.. code-block:: c
> > > +
> > > + struct rte_acl_ctx *
> > > + -rte_acl_create(const struct rte_acl_param *param);
> > > + +rte_acl_create(const struct rte_acl_param *param, int debug);
> > > + +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
> >
> > Will it work with static library?
> >
> hmm, this example in particular? No, I didn't think of that. To work with a
> static build, you still need to define the unversioned symbol. Thats easy
> enough to do though, by either defining rte_acl_create as a public api and
> calling the appropriate versioned function, or by creating a macro to point to
> the right version via an alias. I can fix that easily enough.
Yes please, static libraries are really important in DPDK.
^ permalink raw reply [relevance 7%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-25 7:19 4% ` Zhang, Helin
2015-06-25 7:42 4% ` Gonzalez Monroy, Sergio
@ 2015-06-25 12:25 4% ` Neil Horman
1 sibling, 0 replies; 200+ results
From: Neil Horman @ 2015-06-25 12:25 UTC (permalink / raw)
To: Zhang, Helin; +Cc: dev
On Thu, Jun 25, 2015 at 07:19:49AM +0000, Zhang, Helin wrote:
>
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> > Sent: Thursday, June 25, 2015 2:35 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
> >
> > People have been asking for ways to use the ABI macros, heres some docs to
> > clarify their use. Included is:
> >
> > * An overview of what ABI is
> > * Details of the ABI deprecation process
> > * Details of the versioning macros
> > * Examples of their use
> > * Details of how to use the ABI validator
> >
> > Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
> > working on it. Much of the introductory material was gathered and cleaned up
> > by him
> >
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > CC: john.mcnamara@intel.com
> > CC: thomas.monjalon@6wind.com
> >
> > Change notes:
> >
> > v2)
> > * Fixed RST indentations and spelling errors
> > * Rebased to upstream to fix index.rst conflict
> > ---
> > doc/guides/guidelines/index.rst | 1 +
> > doc/guides/guidelines/versioning.rst | 456
> > +++++++++++++++++++++++++++++++++++
> > 2 files changed, 457 insertions(+)
> > create mode 100644 doc/guides/guidelines/versioning.rst
> >
> > diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
> > index 0ee9ab3..bfb9fa3 100644
> > --- a/doc/guides/guidelines/index.rst
> > +++ b/doc/guides/guidelines/index.rst
> > @@ -7,3 +7,4 @@ Guidelines
> >
> > coding_style
> > design
> > + versioning
> > diff --git a/doc/guides/guidelines/versioning.rst
> > b/doc/guides/guidelines/versioning.rst
> > new file mode 100644
> > index 0000000..2aef526
> > --- /dev/null
> > +++ b/doc/guides/guidelines/versioning.rst
> > @@ -0,0 +1,456 @@
> > +Managing ABI updates
> > +====================
> > +
> > +Description
> > +-----------
> > +
> > +This document details some methods for handling ABI management in the
> > DPDK.
> > +Note this document is not exhaustive, in that C library versioning is
> > +flexible allowing multiple methods to achieve various goals, but it
> > +will provide the user with some introductory methods
> > +
> > +General Guidelines
> > +------------------
> > +
> > +#. Whenever possible, ABI should be preserved #. The addition of
> > +symbols is generally not problematic #. The modification of symbols can
> > +generally be managed with versioning #. The removal of symbols
> > +generally is an ABI break and requires bumping of the
> > + LIBABIVER macro
> > +
> > +What is an ABI
> > +--------------
> > +
> > +An ABI (Application Binary Interface) is the set of runtime interfaces
> > +exposed by a library. It is similar to an API (Application Programming
> > +Interface) but is the result of compilation. It is also effectively
> > +cloned when applications link to dynamic libraries. That is to say
> > +when an application is compiled to link against dynamic libraries, it
> > +is assumed that the ABI remains constant between the time the application is
> > compiled/linked, and the time that it runs.
> > +Therefore, in the case of dynamic linking, it is critical that an ABI
> > +is preserved, or (when modified), done in such a way that the
> > +application is unable to behave improperly or in an unexpected fashion.
> > +
> > +The DPDK ABI policy
> > +-------------------
> > +
> > +ABI versions are set at the time of major release labeling, and the ABI
> > +may change multiple times, without warning, between the last release
> > +label and the HEAD label of the git tree.
> > +
> > +ABI versions, once released, are available until such time as their
> > +deprecation has been noted in the Release Notes for at least one major
> > +release cycle. For example consider the case where the ABI for DPDK 2.0
> > +has been shipped and then a decision is made to modify it during the
> > +development of DPDK 2.1. The decision will be recorded in the Release
> > +Notes for the DPDK 2.1 release and the modification will be made available in
> > the DPDK 2.2 release.
> > +
> > +ABI versions may be deprecated in whole or in part as needed by a given
> > +update.
> > +
> > +Some ABI changes may be too significant to reasonably maintain multiple
> > +versions. In those cases ABI's may be updated without backward
> > +compatibility being provided. The requirements for doing so are:
> > +
> > +#. At least 3 acknowledgments of the need to do so must be made on the
> > + dpdk.org mailing list.
> > +
> > +#. A full deprecation cycle, as explained above, must be made to offer
> > + downstream consumers sufficient warning of the change.
> > +
> > +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
> > + incorporated must be incremented in parallel with the ABI changes
> > + themselves.
> > +
> > +Note that the above process for ABI deprecation should not be
> > +undertaken lightly. ABI stability is extremely important for downstream
> > +consumers of the DPDK, especially when distributed in shared object
> > +form. Every effort should be made to preserve the ABI whenever
> > +possible. The ABI should only be changed for significant reasons, such
> > +as performance enhancements. ABI breakage due to changes such as
> > +reorganizing public structure fields for aesthetic or readability purposes should
> > be avoided.
> > +
> > +Examples of Deprecation Notices
> > +-------------------------------
> > +
> > +The following are some examples of ABI deprecation notices which would
> > +be added to the Release Notes:
> > +
> > +* The Macro ``#RTE_FOO`` is deprecated and will be removed with version
> > +2.0,
> > + to be replaced with the inline function ``rte_foo()``.
> > +
> > +* The function ``rte_mbuf_grok()`` has been updated to include a new
> > +parameter
> > + in version 2.0. Backwards compatibility will be maintained for this
> > +function
> > + until the release of version 2.1
> > +
> > +* The members of ``struct rte_foo`` have been reorganized in release
> > +2.0 for
> > + performance reasons. Existing binary applications will have backwards
> > + compatibility in release 2.0, while newly built binaries will need to
> > + reference the new structure variant ``struct rte_foo2``.
> > +Compatibility will
> > + be removed in release 2.2, and all applications will require updating
> > +and
> > + rebuilding to the new structure at that time, which will be renamed
> > +to the
> > + original ``struct rte_foo``.
> > +
> > +* Significant ABI changes are planned for the ``librte_dostuff``
> > +library. The
> > + upcoming release 2.0 will not contain these changes, but release 2.1
> > +will,
> > + and no backwards compatibility is planned due to the extensive nature
> > +of
> > + these changes. Binaries using this library built prior to version 2.1
> > +will
> > + require updating and recompilation.
> > +
> > +Versioning Macros
> > +-----------------
> > +
> > +When a symbol is exported from a library to provide an API, it also
> > +provides a calling convention (ABI) that is embodied in its name,
> > +return type and arguments. Occasionally that function may need to
> > +change to accommodate new functionality or behavior. When that occurs,
> > +it is desirable to allow for backward compatibility for a time with
> > +older binaries that are dynamically linked to the DPDK.
> > +
> > +To support backward compatibility the
> > +``lib/librte_compat/rte_compat.h``
> > +header file provides macros to use when updating exported functions.
> > +These macros are used in conjunction with the
> > +``rte_<library>_version.map`` file for a given library to allow
> > +multiple versions of a symbol to exist in a shared library so that older binaries
> > need not be immediately recompiled.
> > +
> > +The macros exported are:
> > +
> > +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry
> > +binding
> > + unversioned symbol ``b`` to the internal function ``b_e``.
> > +
> > +
> > +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> > + unversioned symbol ``b`` to the internal function ``b_e``.
> > +
> > +* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry
> > +instructing
> > + the linker to bind references to symbol ``b`` to the internal symbol
> > + ``b_e``.
> > +
> > +
> > +Examples of ABI Macro use
> > +-------------------------
> > +
> > +Updating a public API
> > +~~~~~~~~~~~~~~~~~~~~~
> > +
> > +Assume we have a function as follows
> > +
> > +.. code-block:: c
> > +
> > + /*
> > + * Create an acl context object for apps to
> > + * manipulate
> > + */
> > + struct rte_acl_ctx *
> > + rte_acl_create(const struct rte_acl_param *param) {
> > + ...
> > + }
> > +
> > +
> > +Assume that struct rte_acl_ctx is a private structure, and that a
> > +developer wishes to enhance the acl api so that a debugging flag can be
> > +enabled on a per-context basis. This requires an addition to the
> > +structure (which, being private, is safe), but it also requires
> > +modifying the code as follows
> > +
> > +.. code-block:: c
> > +
> > + /*
> > + * Create an acl context object for apps to
> > + * manipulate
> > + */
> > + struct rte_acl_ctx *
> > + rte_acl_create(const struct rte_acl_param *param, int debug) {
> > + ...
> > + }
> > +
> > +
> > +Note also that, being a public function, the header file prototype must
> > +also be changed, as must all the call sites, to reflect the new ABI
> > +footprint. We will maintain previous ABI versions that are accessible
> > +only to previously compiled binaries
> > +
> > +The addition of a parameter to the function is ABI breaking as the
> > +function is public, and existing application may use it in its current
> > +form. However, the compatibility macros in DPDK allow a developer to
> > +use symbol versioning so that multiple functions can be mapped to the
> > +same public symbol based on when an application was linked to it. To
> > +see how this is done, we start with the requisite libraries version map
> > +file. Initially the version map file for the acl library looks like
> > +this
> > +
> > +.. code-block:: none
> > +
> > + DPDK_2.0 {
> > + global:
> > +
> > + rte_acl_add_rules;
> > + rte_acl_build;
> > + rte_acl_classify;
> > + rte_acl_classify_alg;
> > + rte_acl_classify_scalar;
> > + rte_acl_create;
> > + rte_acl_dump;
> > + rte_acl_find_existing;
> > + rte_acl_free;
> > + rte_acl_ipv4vlan_add_rules;
> > + rte_acl_ipv4vlan_build;
> > + rte_acl_list_dump;
> > + rte_acl_reset;
> > + rte_acl_reset_rules;
> > + rte_acl_set_ctx_classify;
> > +
> > + local: *;
> > + };
> > +
> > +This file needs to be modified as follows
> > +
> > +.. code-block:: none
> > +
> > + DPDK_2.0 {
> > + global:
> > +
> > + rte_acl_add_rules;
> > + rte_acl_build;
> > + rte_acl_classify;
> > + rte_acl_classify_alg;
> > + rte_acl_classify_scalar;
> > + rte_acl_create;
> > + rte_acl_dump;
> > + rte_acl_find_existing;
> > + rte_acl_free;
> > + rte_acl_ipv4vlan_add_rules;
> > + rte_acl_ipv4vlan_build;
> > + rte_acl_list_dump;
> > + rte_acl_reset;
> > + rte_acl_reset_rules;
> > + rte_acl_set_ctx_classify;
> > +
> > + local: *;
> > + };
> > +
> > + DPDK_2.1 {
> > + global:
> > + rte_acl_create;
> One question, does it need a line of "local: *;", like it did in
> librte_ether/rte_ether_version.map?
>
It shouldn't. local just specifies that any symbol not already declared global
be unpublished in the ELF file (i.e. not global). You can declare it again in
the next version node, but since the 2.1 node inherits from the 2.0 node, its
implied.
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-24 21:09 9% ` Thomas Monjalon
@ 2015-06-25 11:35 9% ` Neil Horman
2015-06-25 13:22 7% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-06-25 11:35 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Wed, Jun 24, 2015 at 11:09:29PM +0200, Thomas Monjalon wrote:
> 2015-06-24 14:34, Neil Horman:
> > +Some ABI changes may be too significant to reasonably maintain multiple
> > +versions. In those cases ABI's may be updated without backward compatibility
> > +being provided. The requirements for doing so are:
> > +
> > +#. At least 3 acknowledgments of the need to do so must be made on the
> > + dpdk.org mailing list.
> > +
> > +#. A full deprecation cycle, as explained above, must be made to offer
> > + downstream consumers sufficient warning of the change.
> > +
> > +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
> > + incorporated must be incremented in parallel with the ABI changes
> > + themselves.
>
> The proposal was to provide the old and the new ABI in the same source code
> during the deprecation cycle. The old ABI would be the default and people
> can build the new one by enabling the NEXT_ABI config option.
> So the migration to the new ABI is smoother.
>
Yes....I'm not sure what you're saying here. The ABI doesn't 'Change' until the
old ABI is removed (i.e. old applications are forced to adopt a new ABI), and so
LIBABIVER has to be updated in parallel with that removal
>
> [...]
> > +The macros exported are:
> > +
> > +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> > + unversioned symbol ``b`` to the internal function ``b_e``.
>
> The definition is the same as BASE_SYMBOL.
>
No, they're different. VERSION_SYMBOL is defined as:
VERSION_SYMBOL(b, e, n) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b) "@DPDK_" RTE_STR(n))
while BASE_SYMBOL is
#define BASE_SYMBOL(b, e) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b)"@")
> > +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> > + unversioned symbol ``b`` to the internal function ``b_e``.
>
>
> [...]
> > + DPDK_2.0 {
> > + global:
> > +
> > + rte_acl_add_rules;
> > + rte_acl_build;
> > + rte_acl_classify;
> > + rte_acl_classify_alg;
> > + rte_acl_classify_scalar;
> > + rte_acl_create;
>
> So it's declared twice, right?
> I think it should be explicit.
>
Yes, its listed once for each version node, so 2 delcarations. I thought that
was made explicit by the use of the code block. What else would you like to
see?
> > + rte_acl_dump;
> > + rte_acl_find_existing;
> > + rte_acl_free;
> > + rte_acl_ipv4vlan_add_rules;
> > + rte_acl_ipv4vlan_build;
> > + rte_acl_list_dump;
> > + rte_acl_reset;
> > + rte_acl_reset_rules;
> > + rte_acl_set_ctx_classify;
> > +
> > + local: *;
> > + };
> > +
> > + DPDK_2.1 {
> > + global:
> > + rte_acl_create;
> > +
> > + } DPDK_2.0;
>
> [...]
> > +Note that the base name of the symbol was kept in tact, as this is condusive to
>
> s/in tact/intact/?
>
Hmm, thats odd, aspell explicitly changed that. Though your right, it should be
intact. I'll fix it.
> [...]
> > +the macros used for versioning symbols. That is our next step, mapping this new
> > +symbol name to the initial symbol name at version node 2.0. Immediately after
> > +the function, we add this line of code
> > +
> > +.. code-block:: c
> > +
> > + VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
>
> Can it be declared before the function?
>
Strictly speaking yes, though its a bit odd from a sylistic point to declare
versioned aliases for a symbol prior to defining the symbol itself (its like a
forward declaration)
> [...]
> > +Remembering to also add the rte_compat.h header to the requisite c file where
> > +these changes are being made. The above macro instructs the linker to create a
> > +new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
> > +builds, but now points to the above newly named function. We have now mapped
> > +the original rte_acl_create symbol to the original function (but with a new
> > +name)
>
> Could we use VERSION_SYMBOL(rte_acl_create, , 2.0);
> when introducing the function in DPDK 2.0 (before any ABI breakage)?
> It could help to generate the .map file.
>
I've honestly not tried. I think its possible, but the example you give above I
don't think will work, because it will result in an error indicating
rte_acl_create is declared twice. You would have to rename rte_acl_create to
something uniqe prior to versioning it.
> When do we need to use BASE_SYMBOL?
>
For our purposes you currently don't, because there are no unversioned symbols
in DPDK (since we use a map file). I've just included it here for completeness
in the header file should it ever be needed in the future.
> [...]
> > +This code serves as our new API call. Its the same as our old call, but adds
> > +the new parameter in place. Next we need to map this function to the symbol
> > +``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call
> > +in the header file, adding the macro there to inform all including applications,
> > +that on re-link, the default rte_acl_create symbol should point to this
> > +function. Note that we could do this by simply naming the function above
> > +rte_acl_create, and the linker would chose the most recent version tag to apply
> > +in the version script, but we can also do this in the header file
> > +
> > +.. code-block:: c
> > +
> > + struct rte_acl_ctx *
> > + -rte_acl_create(const struct rte_acl_param *param);
> > + +rte_acl_create(const struct rte_acl_param *param, int debug);
> > + +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
>
> Will it work with static library?
>
hmm, this example in particular? No, I didn't think of that. To work with a
static build, you still need to define the unversioned symbol. Thats easy
enough to do though, by either defining rte_acl_create as a public api and
calling the appropriate versioned function, or by creating a macro to point to
the right version via an alias. I can fix that easily enough.
> > +Next remove the corresponding versioned export
> > +.. code-block:: c
> > +
> > + -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
> > +
> > +
> > +Note that the internal function definition could also be removed, but its used
> > +in our example by the newer version _v21, so we leave it in place. This is a
> > +coding style choice.
> > +
> > +Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
> > +indicate to applications doing dynamic linking that this is a later, and
> > +possibly incompatible library version:
> > +
> > +.. code-block:: c
> > +
> > + -LIBABIVER := 1
> > + +LIBABIVER := 2
>
> Very well explained, thanks.
>
> [...]
> > + rte_acl_add_rules;
> > + rte_acl_build;
> > + rte_acl_classify;
> > + rte_acl_classify_alg;
> > + rte_acl_classify_scalar;
> > + rte_acl_dump;
> > + rte_acl_create
>
> Not in alphabetical order.
>
No, none of them are, but that can be adjusted, though I'd like to do that
separately from this documentation.
>
> As you copy a part of abi.rst, it should be removed from the original doc.
>
Sure
> Thanks Neil
>
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [PATCH v3 2/7] mbuf: use the reserved 16 bits for double vlan
@ 2015-06-25 8:31 3% ` Zhang, Helin
2015-06-28 20:36 0% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Zhang, Helin @ 2015-06-25 8:31 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
Hi Neil
> -----Original Message-----
> From: Zhang, Helin
> Sent: Thursday, June 11, 2015 3:04 PM
> To: dev@dpdk.org
> Cc: Cao, Min; Liu, Jijiang; Wu, Jingjing; Ananyev, Konstantin; Richardson, Bruce;
> olivier.matz@6wind.com; Zhang, Helin
> Subject: [PATCH v3 2/7] mbuf: use the reserved 16 bits for double vlan
>
> Use the reserved 16 bits in rte_mbuf structure for the outer vlan, also add QinQ
> offloading flags for both RX and TX sides.
>
> Signed-off-by: Helin Zhang <helin.zhang@intel.com>
> ---
> lib/librte_mbuf/rte_mbuf.h | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> v2 changes:
> * Fixed a typo.
>
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index
> ab6de67..84fe181 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -101,11 +101,17 @@ extern "C" {
> #define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet with
> IPv6 header. */
> #define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR match.
> */
> #define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported if
> FDIR match. */
> +#define PKT_RX_QINQ_PKT (1ULL << 15) /**< RX packet with double
> VLAN stripped. */
> /* add new RX flags here */
>
> /* add new TX flags here */
>
> /**
> + * Second VLAN insertion (QinQ) flag.
> + */
> +#define PKT_TX_QINQ_PKT (1ULL << 49) /**< TX packet with double
> VLAN inserted. */
> +
> +/**
> * TCP segmentation offload. To enable this offload feature for a
> * packet to be transmitted on hardware supporting TSO:
> * - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag implies @@
> -279,7 +285,7 @@ struct rte_mbuf {
> uint16_t data_len; /**< Amount of data in segment buffer. */
> uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
> uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
> - uint16_t reserved;
> + uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU
> +order) */
Do you think here is a ABI break or not? Just using the reserved 16 bits, which was
intended for the second_vlan_tag. Thanks in advance!
I did not see any "Incompatible" reported by validate_abi.sh.
Regards,
Helin
> union {
> uint32_t rss; /**< RSS hash result if RSS enabled */
> struct {
> @@ -777,6 +783,7 @@ static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
> m->pkt_len = 0;
> m->tx_offload = 0;
> m->vlan_tci = 0;
> + m->vlan_tci_outer = 0;
> m->nb_segs = 1;
> m->port = 0xff;
>
> @@ -849,6 +856,7 @@ static inline void rte_pktmbuf_attach(struct rte_mbuf *mi,
> struct rte_mbuf *m)
> mi->data_len = m->data_len;
> mi->port = m->port;
> mi->vlan_tci = m->vlan_tci;
> + mi->vlan_tci_outer = m->vlan_tci_outer;
> mi->tx_offload = m->tx_offload;
> mi->hash = m->hash;
>
> --
> 1.9.3
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-25 7:42 4% ` Gonzalez Monroy, Sergio
@ 2015-06-25 8:00 4% ` Gonzalez Monroy, Sergio
0 siblings, 0 replies; 200+ results
From: Gonzalez Monroy, Sergio @ 2015-06-25 8:00 UTC (permalink / raw)
To: Zhang, Helin, Neil Horman, dev
On 25/06/2015 08:42, Gonzalez Monroy, Sergio wrote:
> On 25/06/2015 08:19, Zhang, Helin wrote:
>>
>>> -----Original Message-----
>>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
>>> Sent: Thursday, June 25, 2015 2:35 AM
>>> To: dev@dpdk.org
>>> Subject: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
>>>
>>> People have been asking for ways to use the ABI macros, heres some
>>> docs to
>>> clarify their use. Included is:
>>>
>>> * An overview of what ABI is
>>> * Details of the ABI deprecation process
>>> * Details of the versioning macros
>>> * Examples of their use
>>> * Details of how to use the ABI validator
>>>
>>> Thanks to John Mcnamara, who duplicated much of this effort at Intel
>>> while I was
>>> working on it. Much of the introductory material was gathered and
>>> cleaned up
>>> by him
>>>
>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>> CC: john.mcnamara@intel.com
>>> CC: thomas.monjalon@6wind.com
>>>
>>> Change notes:
>>>
>>> v2)
>>> * Fixed RST indentations and spelling errors
>>> * Rebased to upstream to fix index.rst conflict
>>> ---
>>> doc/guides/guidelines/index.rst | 1 +
>>> doc/guides/guidelines/versioning.rst | 456
>>> +++++++++++++++++++++++++++++++++++
>>> 2 files changed, 457 insertions(+)
>>> create mode 100644 doc/guides/guidelines/versioning.rst
>>>
>>> diff --git a/doc/guides/guidelines/index.rst
>>> b/doc/guides/guidelines/index.rst
>>> index 0ee9ab3..bfb9fa3 100644
>>> --- a/doc/guides/guidelines/index.rst
>>> +++ b/doc/guides/guidelines/index.rst
>>> @@ -7,3 +7,4 @@ Guidelines
>>>
>>> coding_style
>>> design
>>> + versioning
>>> diff --git a/doc/guides/guidelines/versioning.rst
>>> b/doc/guides/guidelines/versioning.rst
>>> new file mode 100644
>>> index 0000000..2aef526
>>> --- /dev/null
>>> +++ b/doc/guides/guidelines/versioning.rst
>>> @@ -0,0 +1,456 @@
>>> +Managing ABI updates
>>> +====================
>>> +
>>> +Description
>>> +-----------
>>> +
>>> +This document details some methods for handling ABI management in the
>>> DPDK.
>>> +Note this document is not exhaustive, in that C library versioning is
>>> +flexible allowing multiple methods to achieve various goals, but it
>>> +will provide the user with some introductory methods
>>> +
>>> +General Guidelines
>>> +------------------
>>> +
>>> +#. Whenever possible, ABI should be preserved #. The addition of
>>> +symbols is generally not problematic #. The modification of symbols
>>> can
>>> +generally be managed with versioning #. The removal of symbols
>>> +generally is an ABI break and requires bumping of the
>>> + LIBABIVER macro
>>> +
>>> +What is an ABI
>>> +--------------
>>> +
>>> +An ABI (Application Binary Interface) is the set of runtime interfaces
>>> +exposed by a library. It is similar to an API (Application Programming
>>> +Interface) but is the result of compilation. It is also effectively
>>> +cloned when applications link to dynamic libraries. That is to say
>>> +when an application is compiled to link against dynamic libraries, it
>>> +is assumed that the ABI remains constant between the time the
>>> application is
>>> compiled/linked, and the time that it runs.
>>> +Therefore, in the case of dynamic linking, it is critical that an ABI
>>> +is preserved, or (when modified), done in such a way that the
>>> +application is unable to behave improperly or in an unexpected
>>> fashion.
>>> +
>>> +The DPDK ABI policy
>>> +-------------------
>>> +
>>> +ABI versions are set at the time of major release labeling, and the
>>> ABI
>>> +may change multiple times, without warning, between the last release
>>> +label and the HEAD label of the git tree.
>>> +
>>> +ABI versions, once released, are available until such time as their
>>> +deprecation has been noted in the Release Notes for at least one major
>>> +release cycle. For example consider the case where the ABI for DPDK
>>> 2.0
>>> +has been shipped and then a decision is made to modify it during the
>>> +development of DPDK 2.1. The decision will be recorded in the Release
>>> +Notes for the DPDK 2.1 release and the modification will be made
>>> available in
>>> the DPDK 2.2 release.
>>> +
>>> +ABI versions may be deprecated in whole or in part as needed by a
>>> given
>>> +update.
>>> +
>>> +Some ABI changes may be too significant to reasonably maintain
>>> multiple
>>> +versions. In those cases ABI's may be updated without backward
>>> +compatibility being provided. The requirements for doing so are:
>>> +
>>> +#. At least 3 acknowledgments of the need to do so must be made on the
>>> + dpdk.org mailing list.
>>> +
>>> +#. A full deprecation cycle, as explained above, must be made to offer
>>> + downstream consumers sufficient warning of the change.
>>> +
>>> +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI
>>> changes are
>>> + incorporated must be incremented in parallel with the ABI changes
>>> + themselves.
>>> +
>>> +Note that the above process for ABI deprecation should not be
>>> +undertaken lightly. ABI stability is extremely important for
>>> downstream
>>> +consumers of the DPDK, especially when distributed in shared object
>>> +form. Every effort should be made to preserve the ABI whenever
>>> +possible. The ABI should only be changed for significant reasons, such
>>> +as performance enhancements. ABI breakage due to changes such as
>>> +reorganizing public structure fields for aesthetic or readability
>>> purposes should
>>> be avoided.
>>> +
>>> +Examples of Deprecation Notices
>>> +-------------------------------
>>> +
>>> +The following are some examples of ABI deprecation notices which would
>>> +be added to the Release Notes:
>>> +
>>> +* The Macro ``#RTE_FOO`` is deprecated and will be removed with
>>> version
>>> +2.0,
>>> + to be replaced with the inline function ``rte_foo()``.
>>> +
>>> +* The function ``rte_mbuf_grok()`` has been updated to include a new
>>> +parameter
>>> + in version 2.0. Backwards compatibility will be maintained for this
>>> +function
>>> + until the release of version 2.1
>>> +
>>> +* The members of ``struct rte_foo`` have been reorganized in release
>>> +2.0 for
>>> + performance reasons. Existing binary applications will have
>>> backwards
>>> + compatibility in release 2.0, while newly built binaries will
>>> need to
>>> + reference the new structure variant ``struct rte_foo2``.
>>> +Compatibility will
>>> + be removed in release 2.2, and all applications will require
>>> updating
>>> +and
>>> + rebuilding to the new structure at that time, which will be renamed
>>> +to the
>>> + original ``struct rte_foo``.
>>> +
>>> +* Significant ABI changes are planned for the ``librte_dostuff``
>>> +library. The
>>> + upcoming release 2.0 will not contain these changes, but release 2.1
>>> +will,
>>> + and no backwards compatibility is planned due to the extensive
>>> nature
>>> +of
>>> + these changes. Binaries using this library built prior to version
>>> 2.1
>>> +will
>>> + require updating and recompilation.
>>> +
>>> +Versioning Macros
>>> +-----------------
>>> +
>>> +When a symbol is exported from a library to provide an API, it also
>>> +provides a calling convention (ABI) that is embodied in its name,
>>> +return type and arguments. Occasionally that function may need to
>>> +change to accommodate new functionality or behavior. When that occurs,
>>> +it is desirable to allow for backward compatibility for a time with
>>> +older binaries that are dynamically linked to the DPDK.
>>> +
>>> +To support backward compatibility the
>>> +``lib/librte_compat/rte_compat.h``
>>> +header file provides macros to use when updating exported functions.
>>> +These macros are used in conjunction with the
>>> +``rte_<library>_version.map`` file for a given library to allow
>>> +multiple versions of a symbol to exist in a shared library so that
>>> older binaries
>>> need not be immediately recompiled.
>>> +
>>> +The macros exported are:
>>> +
>>> +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry
>>> +binding
>>> + unversioned symbol ``b`` to the internal function ``b_e``.
>>> +
>>> +
>>> +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
>>> + unversioned symbol ``b`` to the internal function ``b_e``.
>>> +
>>> +* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry
>>> +instructing
>>> + the linker to bind references to symbol ``b`` to the internal symbol
>>> + ``b_e``.
>>> +
>>> +
>>> +Examples of ABI Macro use
>>> +-------------------------
>>> +
>>> +Updating a public API
>>> +~~~~~~~~~~~~~~~~~~~~~
>>> +
>>> +Assume we have a function as follows
>>> +
>>> +.. code-block:: c
>>> +
>>> + /*
>>> + * Create an acl context object for apps to
>>> + * manipulate
>>> + */
>>> + struct rte_acl_ctx *
>>> + rte_acl_create(const struct rte_acl_param *param) {
>>> + ...
>>> + }
>>> +
>>> +
>>> +Assume that struct rte_acl_ctx is a private structure, and that a
>>> +developer wishes to enhance the acl api so that a debugging flag
>>> can be
>>> +enabled on a per-context basis. This requires an addition to the
>>> +structure (which, being private, is safe), but it also requires
>>> +modifying the code as follows
>>> +
>>> +.. code-block:: c
>>> +
>>> + /*
>>> + * Create an acl context object for apps to
>>> + * manipulate
>>> + */
>>> + struct rte_acl_ctx *
>>> + rte_acl_create(const struct rte_acl_param *param, int debug) {
>>> + ...
>>> + }
>>> +
>>> +
>>> +Note also that, being a public function, the header file prototype
>>> must
>>> +also be changed, as must all the call sites, to reflect the new ABI
>>> +footprint. We will maintain previous ABI versions that are accessible
>>> +only to previously compiled binaries
>>> +
>>> +The addition of a parameter to the function is ABI breaking as the
>>> +function is public, and existing application may use it in its current
>>> +form. However, the compatibility macros in DPDK allow a developer to
>>> +use symbol versioning so that multiple functions can be mapped to the
>>> +same public symbol based on when an application was linked to it. To
>>> +see how this is done, we start with the requisite libraries version
>>> map
>>> +file. Initially the version map file for the acl library looks like
>>> +this
>>> +
>>> +.. code-block:: none
>>> +
>>> + DPDK_2.0 {
>>> + global:
>>> +
>>> + rte_acl_add_rules;
>>> + rte_acl_build;
>>> + rte_acl_classify;
>>> + rte_acl_classify_alg;
>>> + rte_acl_classify_scalar;
>>> + rte_acl_create;
>>> + rte_acl_dump;
>>> + rte_acl_find_existing;
>>> + rte_acl_free;
>>> + rte_acl_ipv4vlan_add_rules;
>>> + rte_acl_ipv4vlan_build;
>>> + rte_acl_list_dump;
>>> + rte_acl_reset;
>>> + rte_acl_reset_rules;
>>> + rte_acl_set_ctx_classify;
>>> +
>>> + local: *;
>>> + };
>>> +
>>> +This file needs to be modified as follows
>>> +
>>> +.. code-block:: none
>>> +
>>> + DPDK_2.0 {
>>> + global:
>>> +
>>> + rte_acl_add_rules;
>>> + rte_acl_build;
>>> + rte_acl_classify;
>>> + rte_acl_classify_alg;
>>> + rte_acl_classify_scalar;
>>> + rte_acl_create;
>>> + rte_acl_dump;
>>> + rte_acl_find_existing;
>>> + rte_acl_free;
>>> + rte_acl_ipv4vlan_add_rules;
>>> + rte_acl_ipv4vlan_build;
>>> + rte_acl_list_dump;
>>> + rte_acl_reset;
>>> + rte_acl_reset_rules;
>>> + rte_acl_set_ctx_classify;
>>> +
>>> + local: *;
>>> + };
>>> +
>>> + DPDK_2.1 {
>>> + global:
>>> + rte_acl_create;
>> One question, does it need a line of "local: *;", like it did in
>> librte_ether/rte_ether_version.map?
> No, it does not. You only need to specify 'local' in the default/base
> node, which
> in this case/example is DPDK_2.0.
>
> Sergio
Just to be clear, as I think I may have misused the term 'default' here,
it is recommended
to just specify 'local: *;' in just one node (it could confuse the
linker) and it doesn't really
matter which one.
Quoting http://www.akkadia.org/drepper/symbol-versioning:
"It makes no sense at all to associate versions with symbols which are
not exported. Therefore the `local:' sections of all but the base
version are empty and the `local:' section of the base version simply
contains `*'. This will match all symbols which are not explicitly
mentioned in any `global:' list."
Sergio
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-25 7:19 4% ` Zhang, Helin
@ 2015-06-25 7:42 4% ` Gonzalez Monroy, Sergio
2015-06-25 8:00 4% ` Gonzalez Monroy, Sergio
2015-06-25 12:25 4% ` Neil Horman
1 sibling, 1 reply; 200+ results
From: Gonzalez Monroy, Sergio @ 2015-06-25 7:42 UTC (permalink / raw)
To: Zhang, Helin, Neil Horman, dev
On 25/06/2015 08:19, Zhang, Helin wrote:
>
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
>> Sent: Thursday, June 25, 2015 2:35 AM
>> To: dev@dpdk.org
>> Subject: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
>>
>> People have been asking for ways to use the ABI macros, heres some docs to
>> clarify their use. Included is:
>>
>> * An overview of what ABI is
>> * Details of the ABI deprecation process
>> * Details of the versioning macros
>> * Examples of their use
>> * Details of how to use the ABI validator
>>
>> Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
>> working on it. Much of the introductory material was gathered and cleaned up
>> by him
>>
>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>> CC: john.mcnamara@intel.com
>> CC: thomas.monjalon@6wind.com
>>
>> Change notes:
>>
>> v2)
>> * Fixed RST indentations and spelling errors
>> * Rebased to upstream to fix index.rst conflict
>> ---
>> doc/guides/guidelines/index.rst | 1 +
>> doc/guides/guidelines/versioning.rst | 456
>> +++++++++++++++++++++++++++++++++++
>> 2 files changed, 457 insertions(+)
>> create mode 100644 doc/guides/guidelines/versioning.rst
>>
>> diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
>> index 0ee9ab3..bfb9fa3 100644
>> --- a/doc/guides/guidelines/index.rst
>> +++ b/doc/guides/guidelines/index.rst
>> @@ -7,3 +7,4 @@ Guidelines
>>
>> coding_style
>> design
>> + versioning
>> diff --git a/doc/guides/guidelines/versioning.rst
>> b/doc/guides/guidelines/versioning.rst
>> new file mode 100644
>> index 0000000..2aef526
>> --- /dev/null
>> +++ b/doc/guides/guidelines/versioning.rst
>> @@ -0,0 +1,456 @@
>> +Managing ABI updates
>> +====================
>> +
>> +Description
>> +-----------
>> +
>> +This document details some methods for handling ABI management in the
>> DPDK.
>> +Note this document is not exhaustive, in that C library versioning is
>> +flexible allowing multiple methods to achieve various goals, but it
>> +will provide the user with some introductory methods
>> +
>> +General Guidelines
>> +------------------
>> +
>> +#. Whenever possible, ABI should be preserved #. The addition of
>> +symbols is generally not problematic #. The modification of symbols can
>> +generally be managed with versioning #. The removal of symbols
>> +generally is an ABI break and requires bumping of the
>> + LIBABIVER macro
>> +
>> +What is an ABI
>> +--------------
>> +
>> +An ABI (Application Binary Interface) is the set of runtime interfaces
>> +exposed by a library. It is similar to an API (Application Programming
>> +Interface) but is the result of compilation. It is also effectively
>> +cloned when applications link to dynamic libraries. That is to say
>> +when an application is compiled to link against dynamic libraries, it
>> +is assumed that the ABI remains constant between the time the application is
>> compiled/linked, and the time that it runs.
>> +Therefore, in the case of dynamic linking, it is critical that an ABI
>> +is preserved, or (when modified), done in such a way that the
>> +application is unable to behave improperly or in an unexpected fashion.
>> +
>> +The DPDK ABI policy
>> +-------------------
>> +
>> +ABI versions are set at the time of major release labeling, and the ABI
>> +may change multiple times, without warning, between the last release
>> +label and the HEAD label of the git tree.
>> +
>> +ABI versions, once released, are available until such time as their
>> +deprecation has been noted in the Release Notes for at least one major
>> +release cycle. For example consider the case where the ABI for DPDK 2.0
>> +has been shipped and then a decision is made to modify it during the
>> +development of DPDK 2.1. The decision will be recorded in the Release
>> +Notes for the DPDK 2.1 release and the modification will be made available in
>> the DPDK 2.2 release.
>> +
>> +ABI versions may be deprecated in whole or in part as needed by a given
>> +update.
>> +
>> +Some ABI changes may be too significant to reasonably maintain multiple
>> +versions. In those cases ABI's may be updated without backward
>> +compatibility being provided. The requirements for doing so are:
>> +
>> +#. At least 3 acknowledgments of the need to do so must be made on the
>> + dpdk.org mailing list.
>> +
>> +#. A full deprecation cycle, as explained above, must be made to offer
>> + downstream consumers sufficient warning of the change.
>> +
>> +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
>> + incorporated must be incremented in parallel with the ABI changes
>> + themselves.
>> +
>> +Note that the above process for ABI deprecation should not be
>> +undertaken lightly. ABI stability is extremely important for downstream
>> +consumers of the DPDK, especially when distributed in shared object
>> +form. Every effort should be made to preserve the ABI whenever
>> +possible. The ABI should only be changed for significant reasons, such
>> +as performance enhancements. ABI breakage due to changes such as
>> +reorganizing public structure fields for aesthetic or readability purposes should
>> be avoided.
>> +
>> +Examples of Deprecation Notices
>> +-------------------------------
>> +
>> +The following are some examples of ABI deprecation notices which would
>> +be added to the Release Notes:
>> +
>> +* The Macro ``#RTE_FOO`` is deprecated and will be removed with version
>> +2.0,
>> + to be replaced with the inline function ``rte_foo()``.
>> +
>> +* The function ``rte_mbuf_grok()`` has been updated to include a new
>> +parameter
>> + in version 2.0. Backwards compatibility will be maintained for this
>> +function
>> + until the release of version 2.1
>> +
>> +* The members of ``struct rte_foo`` have been reorganized in release
>> +2.0 for
>> + performance reasons. Existing binary applications will have backwards
>> + compatibility in release 2.0, while newly built binaries will need to
>> + reference the new structure variant ``struct rte_foo2``.
>> +Compatibility will
>> + be removed in release 2.2, and all applications will require updating
>> +and
>> + rebuilding to the new structure at that time, which will be renamed
>> +to the
>> + original ``struct rte_foo``.
>> +
>> +* Significant ABI changes are planned for the ``librte_dostuff``
>> +library. The
>> + upcoming release 2.0 will not contain these changes, but release 2.1
>> +will,
>> + and no backwards compatibility is planned due to the extensive nature
>> +of
>> + these changes. Binaries using this library built prior to version 2.1
>> +will
>> + require updating and recompilation.
>> +
>> +Versioning Macros
>> +-----------------
>> +
>> +When a symbol is exported from a library to provide an API, it also
>> +provides a calling convention (ABI) that is embodied in its name,
>> +return type and arguments. Occasionally that function may need to
>> +change to accommodate new functionality or behavior. When that occurs,
>> +it is desirable to allow for backward compatibility for a time with
>> +older binaries that are dynamically linked to the DPDK.
>> +
>> +To support backward compatibility the
>> +``lib/librte_compat/rte_compat.h``
>> +header file provides macros to use when updating exported functions.
>> +These macros are used in conjunction with the
>> +``rte_<library>_version.map`` file for a given library to allow
>> +multiple versions of a symbol to exist in a shared library so that older binaries
>> need not be immediately recompiled.
>> +
>> +The macros exported are:
>> +
>> +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry
>> +binding
>> + unversioned symbol ``b`` to the internal function ``b_e``.
>> +
>> +
>> +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
>> + unversioned symbol ``b`` to the internal function ``b_e``.
>> +
>> +* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry
>> +instructing
>> + the linker to bind references to symbol ``b`` to the internal symbol
>> + ``b_e``.
>> +
>> +
>> +Examples of ABI Macro use
>> +-------------------------
>> +
>> +Updating a public API
>> +~~~~~~~~~~~~~~~~~~~~~
>> +
>> +Assume we have a function as follows
>> +
>> +.. code-block:: c
>> +
>> + /*
>> + * Create an acl context object for apps to
>> + * manipulate
>> + */
>> + struct rte_acl_ctx *
>> + rte_acl_create(const struct rte_acl_param *param) {
>> + ...
>> + }
>> +
>> +
>> +Assume that struct rte_acl_ctx is a private structure, and that a
>> +developer wishes to enhance the acl api so that a debugging flag can be
>> +enabled on a per-context basis. This requires an addition to the
>> +structure (which, being private, is safe), but it also requires
>> +modifying the code as follows
>> +
>> +.. code-block:: c
>> +
>> + /*
>> + * Create an acl context object for apps to
>> + * manipulate
>> + */
>> + struct rte_acl_ctx *
>> + rte_acl_create(const struct rte_acl_param *param, int debug) {
>> + ...
>> + }
>> +
>> +
>> +Note also that, being a public function, the header file prototype must
>> +also be changed, as must all the call sites, to reflect the new ABI
>> +footprint. We will maintain previous ABI versions that are accessible
>> +only to previously compiled binaries
>> +
>> +The addition of a parameter to the function is ABI breaking as the
>> +function is public, and existing application may use it in its current
>> +form. However, the compatibility macros in DPDK allow a developer to
>> +use symbol versioning so that multiple functions can be mapped to the
>> +same public symbol based on when an application was linked to it. To
>> +see how this is done, we start with the requisite libraries version map
>> +file. Initially the version map file for the acl library looks like
>> +this
>> +
>> +.. code-block:: none
>> +
>> + DPDK_2.0 {
>> + global:
>> +
>> + rte_acl_add_rules;
>> + rte_acl_build;
>> + rte_acl_classify;
>> + rte_acl_classify_alg;
>> + rte_acl_classify_scalar;
>> + rte_acl_create;
>> + rte_acl_dump;
>> + rte_acl_find_existing;
>> + rte_acl_free;
>> + rte_acl_ipv4vlan_add_rules;
>> + rte_acl_ipv4vlan_build;
>> + rte_acl_list_dump;
>> + rte_acl_reset;
>> + rte_acl_reset_rules;
>> + rte_acl_set_ctx_classify;
>> +
>> + local: *;
>> + };
>> +
>> +This file needs to be modified as follows
>> +
>> +.. code-block:: none
>> +
>> + DPDK_2.0 {
>> + global:
>> +
>> + rte_acl_add_rules;
>> + rte_acl_build;
>> + rte_acl_classify;
>> + rte_acl_classify_alg;
>> + rte_acl_classify_scalar;
>> + rte_acl_create;
>> + rte_acl_dump;
>> + rte_acl_find_existing;
>> + rte_acl_free;
>> + rte_acl_ipv4vlan_add_rules;
>> + rte_acl_ipv4vlan_build;
>> + rte_acl_list_dump;
>> + rte_acl_reset;
>> + rte_acl_reset_rules;
>> + rte_acl_set_ctx_classify;
>> +
>> + local: *;
>> + };
>> +
>> + DPDK_2.1 {
>> + global:
>> + rte_acl_create;
> One question, does it need a line of "local: *;", like it did in
> librte_ether/rte_ether_version.map?
No, it does not. You only need to specify 'local' in the default/base
node, which
in this case/example is DPDK_2.0.
Sergio
>> +
>> + } DPDK_2.0;
>> +
>>
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-24 18:34 14% ` [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation Neil Horman
2015-06-24 21:09 9% ` Thomas Monjalon
@ 2015-06-25 7:19 4% ` Zhang, Helin
2015-06-25 7:42 4% ` Gonzalez Monroy, Sergio
2015-06-25 12:25 4% ` Neil Horman
1 sibling, 2 replies; 200+ results
From: Zhang, Helin @ 2015-06-25 7:19 UTC (permalink / raw)
To: Neil Horman, dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> Sent: Thursday, June 25, 2015 2:35 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
>
> People have been asking for ways to use the ABI macros, heres some docs to
> clarify their use. Included is:
>
> * An overview of what ABI is
> * Details of the ABI deprecation process
> * Details of the versioning macros
> * Examples of their use
> * Details of how to use the ABI validator
>
> Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
> working on it. Much of the introductory material was gathered and cleaned up
> by him
>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: john.mcnamara@intel.com
> CC: thomas.monjalon@6wind.com
>
> Change notes:
>
> v2)
> * Fixed RST indentations and spelling errors
> * Rebased to upstream to fix index.rst conflict
> ---
> doc/guides/guidelines/index.rst | 1 +
> doc/guides/guidelines/versioning.rst | 456
> +++++++++++++++++++++++++++++++++++
> 2 files changed, 457 insertions(+)
> create mode 100644 doc/guides/guidelines/versioning.rst
>
> diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
> index 0ee9ab3..bfb9fa3 100644
> --- a/doc/guides/guidelines/index.rst
> +++ b/doc/guides/guidelines/index.rst
> @@ -7,3 +7,4 @@ Guidelines
>
> coding_style
> design
> + versioning
> diff --git a/doc/guides/guidelines/versioning.rst
> b/doc/guides/guidelines/versioning.rst
> new file mode 100644
> index 0000000..2aef526
> --- /dev/null
> +++ b/doc/guides/guidelines/versioning.rst
> @@ -0,0 +1,456 @@
> +Managing ABI updates
> +====================
> +
> +Description
> +-----------
> +
> +This document details some methods for handling ABI management in the
> DPDK.
> +Note this document is not exhaustive, in that C library versioning is
> +flexible allowing multiple methods to achieve various goals, but it
> +will provide the user with some introductory methods
> +
> +General Guidelines
> +------------------
> +
> +#. Whenever possible, ABI should be preserved #. The addition of
> +symbols is generally not problematic #. The modification of symbols can
> +generally be managed with versioning #. The removal of symbols
> +generally is an ABI break and requires bumping of the
> + LIBABIVER macro
> +
> +What is an ABI
> +--------------
> +
> +An ABI (Application Binary Interface) is the set of runtime interfaces
> +exposed by a library. It is similar to an API (Application Programming
> +Interface) but is the result of compilation. It is also effectively
> +cloned when applications link to dynamic libraries. That is to say
> +when an application is compiled to link against dynamic libraries, it
> +is assumed that the ABI remains constant between the time the application is
> compiled/linked, and the time that it runs.
> +Therefore, in the case of dynamic linking, it is critical that an ABI
> +is preserved, or (when modified), done in such a way that the
> +application is unable to behave improperly or in an unexpected fashion.
> +
> +The DPDK ABI policy
> +-------------------
> +
> +ABI versions are set at the time of major release labeling, and the ABI
> +may change multiple times, without warning, between the last release
> +label and the HEAD label of the git tree.
> +
> +ABI versions, once released, are available until such time as their
> +deprecation has been noted in the Release Notes for at least one major
> +release cycle. For example consider the case where the ABI for DPDK 2.0
> +has been shipped and then a decision is made to modify it during the
> +development of DPDK 2.1. The decision will be recorded in the Release
> +Notes for the DPDK 2.1 release and the modification will be made available in
> the DPDK 2.2 release.
> +
> +ABI versions may be deprecated in whole or in part as needed by a given
> +update.
> +
> +Some ABI changes may be too significant to reasonably maintain multiple
> +versions. In those cases ABI's may be updated without backward
> +compatibility being provided. The requirements for doing so are:
> +
> +#. At least 3 acknowledgments of the need to do so must be made on the
> + dpdk.org mailing list.
> +
> +#. A full deprecation cycle, as explained above, must be made to offer
> + downstream consumers sufficient warning of the change.
> +
> +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
> + incorporated must be incremented in parallel with the ABI changes
> + themselves.
> +
> +Note that the above process for ABI deprecation should not be
> +undertaken lightly. ABI stability is extremely important for downstream
> +consumers of the DPDK, especially when distributed in shared object
> +form. Every effort should be made to preserve the ABI whenever
> +possible. The ABI should only be changed for significant reasons, such
> +as performance enhancements. ABI breakage due to changes such as
> +reorganizing public structure fields for aesthetic or readability purposes should
> be avoided.
> +
> +Examples of Deprecation Notices
> +-------------------------------
> +
> +The following are some examples of ABI deprecation notices which would
> +be added to the Release Notes:
> +
> +* The Macro ``#RTE_FOO`` is deprecated and will be removed with version
> +2.0,
> + to be replaced with the inline function ``rte_foo()``.
> +
> +* The function ``rte_mbuf_grok()`` has been updated to include a new
> +parameter
> + in version 2.0. Backwards compatibility will be maintained for this
> +function
> + until the release of version 2.1
> +
> +* The members of ``struct rte_foo`` have been reorganized in release
> +2.0 for
> + performance reasons. Existing binary applications will have backwards
> + compatibility in release 2.0, while newly built binaries will need to
> + reference the new structure variant ``struct rte_foo2``.
> +Compatibility will
> + be removed in release 2.2, and all applications will require updating
> +and
> + rebuilding to the new structure at that time, which will be renamed
> +to the
> + original ``struct rte_foo``.
> +
> +* Significant ABI changes are planned for the ``librte_dostuff``
> +library. The
> + upcoming release 2.0 will not contain these changes, but release 2.1
> +will,
> + and no backwards compatibility is planned due to the extensive nature
> +of
> + these changes. Binaries using this library built prior to version 2.1
> +will
> + require updating and recompilation.
> +
> +Versioning Macros
> +-----------------
> +
> +When a symbol is exported from a library to provide an API, it also
> +provides a calling convention (ABI) that is embodied in its name,
> +return type and arguments. Occasionally that function may need to
> +change to accommodate new functionality or behavior. When that occurs,
> +it is desirable to allow for backward compatibility for a time with
> +older binaries that are dynamically linked to the DPDK.
> +
> +To support backward compatibility the
> +``lib/librte_compat/rte_compat.h``
> +header file provides macros to use when updating exported functions.
> +These macros are used in conjunction with the
> +``rte_<library>_version.map`` file for a given library to allow
> +multiple versions of a symbol to exist in a shared library so that older binaries
> need not be immediately recompiled.
> +
> +The macros exported are:
> +
> +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry
> +binding
> + unversioned symbol ``b`` to the internal function ``b_e``.
> +
> +
> +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> + unversioned symbol ``b`` to the internal function ``b_e``.
> +
> +* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry
> +instructing
> + the linker to bind references to symbol ``b`` to the internal symbol
> + ``b_e``.
> +
> +
> +Examples of ABI Macro use
> +-------------------------
> +
> +Updating a public API
> +~~~~~~~~~~~~~~~~~~~~~
> +
> +Assume we have a function as follows
> +
> +.. code-block:: c
> +
> + /*
> + * Create an acl context object for apps to
> + * manipulate
> + */
> + struct rte_acl_ctx *
> + rte_acl_create(const struct rte_acl_param *param) {
> + ...
> + }
> +
> +
> +Assume that struct rte_acl_ctx is a private structure, and that a
> +developer wishes to enhance the acl api so that a debugging flag can be
> +enabled on a per-context basis. This requires an addition to the
> +structure (which, being private, is safe), but it also requires
> +modifying the code as follows
> +
> +.. code-block:: c
> +
> + /*
> + * Create an acl context object for apps to
> + * manipulate
> + */
> + struct rte_acl_ctx *
> + rte_acl_create(const struct rte_acl_param *param, int debug) {
> + ...
> + }
> +
> +
> +Note also that, being a public function, the header file prototype must
> +also be changed, as must all the call sites, to reflect the new ABI
> +footprint. We will maintain previous ABI versions that are accessible
> +only to previously compiled binaries
> +
> +The addition of a parameter to the function is ABI breaking as the
> +function is public, and existing application may use it in its current
> +form. However, the compatibility macros in DPDK allow a developer to
> +use symbol versioning so that multiple functions can be mapped to the
> +same public symbol based on when an application was linked to it. To
> +see how this is done, we start with the requisite libraries version map
> +file. Initially the version map file for the acl library looks like
> +this
> +
> +.. code-block:: none
> +
> + DPDK_2.0 {
> + global:
> +
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_create;
> + rte_acl_dump;
> + rte_acl_find_existing;
> + rte_acl_free;
> + rte_acl_ipv4vlan_add_rules;
> + rte_acl_ipv4vlan_build;
> + rte_acl_list_dump;
> + rte_acl_reset;
> + rte_acl_reset_rules;
> + rte_acl_set_ctx_classify;
> +
> + local: *;
> + };
> +
> +This file needs to be modified as follows
> +
> +.. code-block:: none
> +
> + DPDK_2.0 {
> + global:
> +
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_create;
> + rte_acl_dump;
> + rte_acl_find_existing;
> + rte_acl_free;
> + rte_acl_ipv4vlan_add_rules;
> + rte_acl_ipv4vlan_build;
> + rte_acl_list_dump;
> + rte_acl_reset;
> + rte_acl_reset_rules;
> + rte_acl_set_ctx_classify;
> +
> + local: *;
> + };
> +
> + DPDK_2.1 {
> + global:
> + rte_acl_create;
One question, does it need a line of "local: *;", like it did in
librte_ether/rte_ether_version.map?
> +
> + } DPDK_2.0;
> +
> +The addition of the new block tells the linker that a new version node
> +is available (DPDK_2.1), which contains the symbol rte_acl_create, and
> +inherits the symbols from the DPDK_2.0 node. This list is directly
> +translated into a list of exported symbols when DPDK is compiled as a
> +shared library
> +
> +Next, we need to specify in the code which function map to the
> +rte_acl_create symbol at which versions. First, at the site of the
> +initial symbol definition, we need to update the function so that it is
> +uniquely named, and not in conflict with the public symbol name
> +
> +.. code-block:: c
> +
> + struct rte_acl_ctx *
> + -rte_acl_create(const struct rte_acl_param *param)
> + +rte_acl_create_v20(const struct rte_acl_param *param)
> + {
> + size_t sz;
> + struct rte_acl_ctx *ctx;
> + ...
> +
> +Note that the base name of the symbol was kept in tact, as this is
> +condusive to the macros used for versioning symbols. That is our next
> +step, mapping this new symbol name to the initial symbol name at
> +version node 2.0. Immediately after the function, we add this line of
> +code
> +
> +.. code-block:: c
> +
> + VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
> +
> +Remembering to also add the rte_compat.h header to the requisite c file
> +where these changes are being made. The above macro instructs the
> +linker to create a new symbol ``rte_acl_create@DPDK_2.0``, which
> +matches the symbol created in older builds, but now points to the above
> +newly named function. We have now mapped the original rte_acl_create
> +symbol to the original function (but with a new
> +name)
> +
> +Next, we need to create the 2.1 version of the symbol. We create a new
> +function name, with a different suffix, and implement it appropriately
> +
> +.. code-block:: c
> +
> + struct rte_acl_ctx *
> + rte_acl_create_v21(const struct rte_acl_param *param, int debug);
> + {
> + struct rte_acl_ctx *ctx = rte_acl_create_v20(param);
> +
> + ctx->debug = debug;
> +
> + return ctx;
> + }
> +
> +This code serves as our new API call. Its the same as our old call,
> +but adds the new parameter in place. Next we need to map this function
> +to the symbol ``rte_acl_create@DPDK_2.1``. To do this, we modify the
> +public prototype of the call in the header file, adding the macro there
> +to inform all including applications, that on re-link, the default
> +rte_acl_create symbol should point to this function. Note that we
> +could do this by simply naming the function above rte_acl_create, and
> +the linker would chose the most recent version tag to apply in the
> +version script, but we can also do this in the header file
> +
> +.. code-block:: c
> +
> + struct rte_acl_ctx *
> + -rte_acl_create(const struct rte_acl_param *param);
> + +rte_acl_create(const struct rte_acl_param *param, int debug);
> + +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
> +
> +The BIND_DEFAULT_SYMBOL macro explicitly tells applications that
> +include this header, to link to the rte_acl_create_v21 function and
> +apply the DPDK_2.1 version node to it. This method is more explicit
> +and flexible than just re-implementing the exact symbol name, and
> +allows for other features (such as linking to the old symbol version by
> +default, when the new ABI is to be opt-in for a period.
> +
> +That's it, on the next shared library rebuild, there will be two
> +versions of rte_acl_create, an old DPDK_2.0 version, used by previously
> +built applications, and a new DPDK_2.1 version, used by future built
> applications.
> +
> +
> +Deprecating part of a public API
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Lets assume that you've done the above update, and after a few releases
> +have passed you decide you would like to retire the old version of the function.
> +After having gone through the ABI deprecation announcement process,
> +removal is easy. Start by removing the symbol from the requisite version map
> file:
> +
> +.. code-block:: none
> +
> + DPDK_2.0 {
> + global:
> +
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_dump;
> + - rte_acl_create
> + rte_acl_find_existing;
> + rte_acl_free;
> + rte_acl_ipv4vlan_add_rules;
> + rte_acl_ipv4vlan_build;
> + rte_acl_list_dump;
> + rte_acl_reset;
> + rte_acl_reset_rules;
> + rte_acl_set_ctx_classify;
> +
> + local: *;
> + };
> +
> + DPDK_2.1 {
> + global:
> + rte_acl_create;
> + } DPDK_2.0;
> +
> +
> +Next remove the corresponding versioned export .. code-block:: c
> +
> + -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
> +
> +
> +Note that the internal function definition could also be removed, but
> +its used in our example by the newer version _v21, so we leave it in
> +place. This is a coding style choice.
> +
> +Lastly, we need to bump the LIBABIVER number for this library in the
> +Makefile to indicate to applications doing dynamic linking that this is
> +a later, and possibly incompatible library version:
> +
> +.. code-block:: c
> +
> + -LIBABIVER := 1
> + +LIBABIVER := 2
> +
> +Deprecating an entire ABI version
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +While removing a symbol from and ABI may be useful, it is often more
> +practical to remove an entire version node at once. If a version node
> +completely specifies an API, then removing part of it, typically makes
> +it incomplete. In those cases it is better to remove the entire node
> +
> +To do this, start by modifying the version map file, such that all
> +symbols from the node to be removed are merged into the next node in
> +the map
> +
> +In the case of our map above, it would transform to look as follows
> +
> +.. code-block:: none
> +
> + DPDK_2.1 {
> + global:
> +
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_dump;
> + rte_acl_create
> + rte_acl_find_existing;
> + rte_acl_free;
> + rte_acl_ipv4vlan_add_rules;
> + rte_acl_ipv4vlan_build;
> + rte_acl_list_dump;
> + rte_acl_reset;
> + rte_acl_reset_rules;
> + rte_acl_set_ctx_classify;
> +
> + local: *;
> + };
> +
> +Then any uses of BIND_DEFAULT_SYMBOL that pointed to the old node
> +should be updated to point to the new version node in any header files
> +for all affected symbols.
> +
> +.. code-block:: c
> +
> + -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
> + +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
> +
> +Lastly, any VERSION_SYMBOL macros that point to the old version node
> +should be removed, taking care to keep, where need old code in place to
> +support newer versions of the symbol.
> +
> +Running the ABI Validator
> +-------------------------
> +
> +The ``scripts`` directory in the DPDK source tree contains a utility
> +program, ``validate-abi.sh``, for validating the DPDK ABI based on the
> +Linux `ABI Compliance Checker
> +<http://ispras.linuxbase.org/index.php/ABI_compliance_checker>`_.
> +
> +This has a dependency on the ``abi-compliance-checker`` and ``and
> +abi-dumper`` utilities which can be installed via a package manager. For
> example::
> +
> + sudo yum install abi-compliance-checker
> + sudo yum install abi-dumper
> +
> +The syntax of the ``validate-abi.sh`` utility is::
> +
> + ./scripts/validate-abi.sh <TAG1> <TAG2> <TARGET>
> +
> +Where ``TAG1`` and ``TAG2`` are valid git tags on the local repo and
> +target is the usual DPDK compilation target.
> +
> +For example to test the current committed HEAD against a previous
> +release tag we could add a temporary tag and run the utility as follows::
> +
> + git tag MY_TEMP_TAG
> + ./scripts/validate-abi.sh v2.0.0 MY_TEMP_TAG
> + x86_64-native-linuxapp-gcc
> +
> +After the validation script completes (it can take a while since it
> +need to compile both tags) it will create compatibility reports in the
> +``./compat_report`` directory. Listed incompatibilities can be found as
> +follows::
> +
> + grep -lr Incompatible compat_reports/
> --
> 2.1.0
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
2015-06-24 18:34 14% ` [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation Neil Horman
@ 2015-06-24 21:09 9% ` Thomas Monjalon
2015-06-25 11:35 9% ` Neil Horman
2015-06-25 7:19 4% ` Zhang, Helin
1 sibling, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-24 21:09 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-24 14:34, Neil Horman:
> +Some ABI changes may be too significant to reasonably maintain multiple
> +versions. In those cases ABI's may be updated without backward compatibility
> +being provided. The requirements for doing so are:
> +
> +#. At least 3 acknowledgments of the need to do so must be made on the
> + dpdk.org mailing list.
> +
> +#. A full deprecation cycle, as explained above, must be made to offer
> + downstream consumers sufficient warning of the change.
> +
> +#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
> + incorporated must be incremented in parallel with the ABI changes
> + themselves.
The proposal was to provide the old and the new ABI in the same source code
during the deprecation cycle. The old ABI would be the default and people
can build the new one by enabling the NEXT_ABI config option.
So the migration to the new ABI is smoother.
[...]
> +The macros exported are:
> +
> +* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
> + unversioned symbol ``b`` to the internal function ``b_e``.
The definition is the same as BASE_SYMBOL.
> +* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
> + unversioned symbol ``b`` to the internal function ``b_e``.
[...]
> + DPDK_2.0 {
> + global:
> +
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_create;
So it's declared twice, right?
I think it should be explicit.
> + rte_acl_dump;
> + rte_acl_find_existing;
> + rte_acl_free;
> + rte_acl_ipv4vlan_add_rules;
> + rte_acl_ipv4vlan_build;
> + rte_acl_list_dump;
> + rte_acl_reset;
> + rte_acl_reset_rules;
> + rte_acl_set_ctx_classify;
> +
> + local: *;
> + };
> +
> + DPDK_2.1 {
> + global:
> + rte_acl_create;
> +
> + } DPDK_2.0;
[...]
> +Note that the base name of the symbol was kept in tact, as this is condusive to
s/in tact/intact/?
[...]
> +the macros used for versioning symbols. That is our next step, mapping this new
> +symbol name to the initial symbol name at version node 2.0. Immediately after
> +the function, we add this line of code
> +
> +.. code-block:: c
> +
> + VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
Can it be declared before the function?
[...]
> +Remembering to also add the rte_compat.h header to the requisite c file where
> +these changes are being made. The above macro instructs the linker to create a
> +new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
> +builds, but now points to the above newly named function. We have now mapped
> +the original rte_acl_create symbol to the original function (but with a new
> +name)
Could we use VERSION_SYMBOL(rte_acl_create, , 2.0);
when introducing the function in DPDK 2.0 (before any ABI breakage)?
It could help to generate the .map file.
When do we need to use BASE_SYMBOL?
[...]
> +This code serves as our new API call. Its the same as our old call, but adds
> +the new parameter in place. Next we need to map this function to the symbol
> +``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call
> +in the header file, adding the macro there to inform all including applications,
> +that on re-link, the default rte_acl_create symbol should point to this
> +function. Note that we could do this by simply naming the function above
> +rte_acl_create, and the linker would chose the most recent version tag to apply
> +in the version script, but we can also do this in the header file
> +
> +.. code-block:: c
> +
> + struct rte_acl_ctx *
> + -rte_acl_create(const struct rte_acl_param *param);
> + +rte_acl_create(const struct rte_acl_param *param, int debug);
> + +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
Will it work with static library?
> +Next remove the corresponding versioned export
> +.. code-block:: c
> +
> + -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
> +
> +
> +Note that the internal function definition could also be removed, but its used
> +in our example by the newer version _v21, so we leave it in place. This is a
> +coding style choice.
> +
> +Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
> +indicate to applications doing dynamic linking that this is a later, and
> +possibly incompatible library version:
> +
> +.. code-block:: c
> +
> + -LIBABIVER := 1
> + +LIBABIVER := 2
Very well explained, thanks.
[...]
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_dump;
> + rte_acl_create
Not in alphabetical order.
As you copy a part of abi.rst, it should be removed from the original doc.
Thanks Neil
^ permalink raw reply [relevance 9%]
* [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation
@ 2015-06-24 18:34 14% ` Neil Horman
2015-06-24 21:09 9% ` Thomas Monjalon
2015-06-25 7:19 4% ` Zhang, Helin
0 siblings, 2 replies; 200+ results
From: Neil Horman @ 2015-06-24 18:34 UTC (permalink / raw)
To: dev
People have been asking for ways to use the ABI macros, heres some docs to
clarify their use. Included is:
* An overview of what ABI is
* Details of the ABI deprecation process
* Details of the versioning macros
* Examples of their use
* Details of how to use the ABI validator
Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
working on it. Much of the introductory material was gathered and cleaned up by
him
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: john.mcnamara@intel.com
CC: thomas.monjalon@6wind.com
Change notes:
v2)
* Fixed RST indentations and spelling errors
* Rebased to upstream to fix index.rst conflict
---
doc/guides/guidelines/index.rst | 1 +
doc/guides/guidelines/versioning.rst | 456 +++++++++++++++++++++++++++++++++++
2 files changed, 457 insertions(+)
create mode 100644 doc/guides/guidelines/versioning.rst
diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
index 0ee9ab3..bfb9fa3 100644
--- a/doc/guides/guidelines/index.rst
+++ b/doc/guides/guidelines/index.rst
@@ -7,3 +7,4 @@ Guidelines
coding_style
design
+ versioning
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
new file mode 100644
index 0000000..2aef526
--- /dev/null
+++ b/doc/guides/guidelines/versioning.rst
@@ -0,0 +1,456 @@
+Managing ABI updates
+====================
+
+Description
+-----------
+
+This document details some methods for handling ABI management in the DPDK.
+Note this document is not exhaustive, in that C library versioning is flexible
+allowing multiple methods to achieve various goals, but it will provide the user
+with some introductory methods
+
+General Guidelines
+------------------
+
+#. Whenever possible, ABI should be preserved
+#. The addition of symbols is generally not problematic
+#. The modification of symbols can generally be managed with versioning
+#. The removal of symbols generally is an ABI break and requires bumping of the
+ LIBABIVER macro
+
+What is an ABI
+--------------
+
+An ABI (Application Binary Interface) is the set of runtime interfaces exposed
+by a library. It is similar to an API (Application Programming Interface) but
+is the result of compilation. It is also effectively cloned when applications
+link to dynamic libraries. That is to say when an application is compiled to
+link against dynamic libraries, it is assumed that the ABI remains constant
+between the time the application is compiled/linked, and the time that it runs.
+Therefore, in the case of dynamic linking, it is critical that an ABI is
+preserved, or (when modified), done in such a way that the application is unable
+to behave improperly or in an unexpected fashion.
+
+The DPDK ABI policy
+-------------------
+
+ABI versions are set at the time of major release labeling, and the ABI may
+change multiple times, without warning, between the last release label and the
+HEAD label of the git tree.
+
+ABI versions, once released, are available until such time as their
+deprecation has been noted in the Release Notes for at least one major release
+cycle. For example consider the case where the ABI for DPDK 2.0 has been
+shipped and then a decision is made to modify it during the development of
+DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1
+release and the modification will be made available in the DPDK 2.2 release.
+
+ABI versions may be deprecated in whole or in part as needed by a given
+update.
+
+Some ABI changes may be too significant to reasonably maintain multiple
+versions. In those cases ABI's may be updated without backward compatibility
+being provided. The requirements for doing so are:
+
+#. At least 3 acknowledgments of the need to do so must be made on the
+ dpdk.org mailing list.
+
+#. A full deprecation cycle, as explained above, must be made to offer
+ downstream consumers sufficient warning of the change.
+
+#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
+ incorporated must be incremented in parallel with the ABI changes
+ themselves.
+
+Note that the above process for ABI deprecation should not be undertaken
+lightly. ABI stability is extremely important for downstream consumers of the
+DPDK, especially when distributed in shared object form. Every effort should
+be made to preserve the ABI whenever possible. The ABI should only be changed
+for significant reasons, such as performance enhancements. ABI breakage due to
+changes such as reorganizing public structure fields for aesthetic or
+readability purposes should be avoided.
+
+Examples of Deprecation Notices
+-------------------------------
+
+The following are some examples of ABI deprecation notices which would be
+added to the Release Notes:
+
+* The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0,
+ to be replaced with the inline function ``rte_foo()``.
+
+* The function ``rte_mbuf_grok()`` has been updated to include a new parameter
+ in version 2.0. Backwards compatibility will be maintained for this function
+ until the release of version 2.1
+
+* The members of ``struct rte_foo`` have been reorganized in release 2.0 for
+ performance reasons. Existing binary applications will have backwards
+ compatibility in release 2.0, while newly built binaries will need to
+ reference the new structure variant ``struct rte_foo2``. Compatibility will
+ be removed in release 2.2, and all applications will require updating and
+ rebuilding to the new structure at that time, which will be renamed to the
+ original ``struct rte_foo``.
+
+* Significant ABI changes are planned for the ``librte_dostuff`` library. The
+ upcoming release 2.0 will not contain these changes, but release 2.1 will,
+ and no backwards compatibility is planned due to the extensive nature of
+ these changes. Binaries using this library built prior to version 2.1 will
+ require updating and recompilation.
+
+Versioning Macros
+-----------------
+
+When a symbol is exported from a library to provide an API, it also provides a
+calling convention (ABI) that is embodied in its name, return type and
+arguments. Occasionally that function may need to change to accommodate new
+functionality or behavior. When that occurs, it is desirable to allow for
+backward compatibility for a time with older binaries that are dynamically
+linked to the DPDK.
+
+To support backward compatibility the ``lib/librte_compat/rte_compat.h``
+header file provides macros to use when updating exported functions. These
+macros are used in conjunction with the ``rte_<library>_version.map`` file for
+a given library to allow multiple versions of a symbol to exist in a shared
+library so that older binaries need not be immediately recompiled.
+
+The macros exported are:
+
+* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
+ unversioned symbol ``b`` to the internal function ``b_e``.
+
+
+* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
+ unversioned symbol ``b`` to the internal function ``b_e``.
+
+* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry instructing
+ the linker to bind references to symbol ``b`` to the internal symbol
+ ``b_e``.
+
+
+Examples of ABI Macro use
+-------------------------
+
+Updating a public API
+~~~~~~~~~~~~~~~~~~~~~
+
+Assume we have a function as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param)
+ {
+ ...
+ }
+
+
+Assume that struct rte_acl_ctx is a private structure, and that a developer
+wishes to enhance the acl api so that a debugging flag can be enabled on a
+per-context basis. This requires an addition to the structure (which, being
+private, is safe), but it also requires modifying the code as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param, int debug)
+ {
+ ...
+ }
+
+
+Note also that, being a public function, the header file prototype must also be
+changed, as must all the call sites, to reflect the new ABI footprint. We will
+maintain previous ABI versions that are accessible only to previously compiled
+binaries
+
+The addition of a parameter to the function is ABI breaking as the function is
+public, and existing application may use it in its current form. However, the
+compatibility macros in DPDK allow a developer to use symbol versioning so that
+multiple functions can be mapped to the same public symbol based on when an
+application was linked to it. To see how this is done, we start with the
+requisite libraries version map file. Initially the version map file for the
+acl library looks like this
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+This file needs to be modified as follows
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+
+ } DPDK_2.0;
+
+The addition of the new block tells the linker that a new version node is
+available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the
+symbols from the DPDK_2.0 node. This list is directly translated into a list of
+exported symbols when DPDK is compiled as a shared library
+
+Next, we need to specify in the code which function map to the rte_acl_create
+symbol at which versions. First, at the site of the initial symbol definition,
+we need to update the function so that it is uniquely named, and not in conflict
+with the public symbol name
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param)
+ +rte_acl_create_v20(const struct rte_acl_param *param)
+ {
+ size_t sz;
+ struct rte_acl_ctx *ctx;
+ ...
+
+Note that the base name of the symbol was kept in tact, as this is condusive to
+the macros used for versioning symbols. That is our next step, mapping this new
+symbol name to the initial symbol name at version node 2.0. Immediately after
+the function, we add this line of code
+
+.. code-block:: c
+
+ VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+Remembering to also add the rte_compat.h header to the requisite c file where
+these changes are being made. The above macro instructs the linker to create a
+new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older
+builds, but now points to the above newly named function. We have now mapped
+the original rte_acl_create symbol to the original function (but with a new
+name)
+
+Next, we need to create the 2.1 version of the symbol. We create a new function
+name, with a different suffix, and implement it appropriately
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ rte_acl_create_v21(const struct rte_acl_param *param, int debug);
+ {
+ struct rte_acl_ctx *ctx = rte_acl_create_v20(param);
+
+ ctx->debug = debug;
+
+ return ctx;
+ }
+
+This code serves as our new API call. Its the same as our old call, but adds
+the new parameter in place. Next we need to map this function to the symbol
+``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call
+in the header file, adding the macro there to inform all including applications,
+that on re-link, the default rte_acl_create symbol should point to this
+function. Note that we could do this by simply naming the function above
+rte_acl_create, and the linker would chose the most recent version tag to apply
+in the version script, but we can also do this in the header file
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param);
+ +rte_acl_create(const struct rte_acl_param *param, int debug);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
+header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1
+version node to it. This method is more explicit and flexible than just
+re-implementing the exact symbol name, and allows for other features (such as
+linking to the old symbol version by default, when the new ABI is to be opt-in
+for a period.
+
+That's it, on the next shared library rebuild, there will be two versions of
+rte_acl_create, an old DPDK_2.0 version, used by previously built applications,
+and a new DPDK_2.1 version, used by future built applications.
+
+
+Deprecating part of a public API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lets assume that you've done the above update, and after a few releases have
+passed you decide you would like to retire the old version of the function.
+After having gone through the ABI deprecation announcement process, removal is
+easy. Start by removing the symbol from the requisite version map file:
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ - rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+ } DPDK_2.0;
+
+
+Next remove the corresponding versioned export
+.. code-block:: c
+
+ -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+
+Note that the internal function definition could also be removed, but its used
+in our example by the newer version _v21, so we leave it in place. This is a
+coding style choice.
+
+Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
+indicate to applications doing dynamic linking that this is a later, and
+possibly incompatible library version:
+
+.. code-block:: c
+
+ -LIBABIVER := 1
+ +LIBABIVER := 2
+
+Deprecating an entire ABI version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+While removing a symbol from and ABI may be useful, it is often more practical
+to remove an entire version node at once. If a version node completely
+specifies an API, then removing part of it, typically makes it incomplete. In
+those cases it is better to remove the entire node
+
+To do this, start by modifying the version map file, such that all symbols from
+the node to be removed are merged into the next node in the map
+
+In the case of our map above, it would transform to look as follows
+
+.. code-block:: none
+
+ DPDK_2.1 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+Then any uses of BIND_DEFAULT_SYMBOL that pointed to the old node should be
+updated to point to the new version node in any header files for all affected
+symbols.
+
+.. code-block:: c
+
+ -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+Lastly, any VERSION_SYMBOL macros that point to the old version node should be
+removed, taking care to keep, where need old code in place to support newer
+versions of the symbol.
+
+Running the ABI Validator
+-------------------------
+
+The ``scripts`` directory in the DPDK source tree contains a utility program,
+``validate-abi.sh``, for validating the DPDK ABI based on the Linux `ABI
+Compliance Checker
+<http://ispras.linuxbase.org/index.php/ABI_compliance_checker>`_.
+
+This has a dependency on the ``abi-compliance-checker`` and ``and abi-dumper``
+utilities which can be installed via a package manager. For example::
+
+ sudo yum install abi-compliance-checker
+ sudo yum install abi-dumper
+
+The syntax of the ``validate-abi.sh`` utility is::
+
+ ./scripts/validate-abi.sh <TAG1> <TAG2> <TARGET>
+
+Where ``TAG1`` and ``TAG2`` are valid git tags on the local repo and target is
+the usual DPDK compilation target.
+
+For example to test the current committed HEAD against a previous release tag
+we could add a temporary tag and run the utility as follows::
+
+ git tag MY_TEMP_TAG
+ ./scripts/validate-abi.sh v2.0.0 MY_TEMP_TAG x86_64-native-linuxapp-gcc
+
+After the validation script completes (it can take a while since it need to
+compile both tags) it will create compatibility reports in the
+``./compat_report`` directory. Listed incompatibilities can be found as
+follows::
+
+ grep -lr Incompatible compat_reports/
--
2.1.0
^ permalink raw reply [relevance 14%]
* Re: [dpdk-dev] [PATCH 2/2] ABI: Add some documentation
2015-06-23 19:33 14% ` [dpdk-dev] [PATCH 2/2] ABI: Add some documentation Neil Horman
@ 2015-06-24 11:21 4% ` Mcnamara, John
0 siblings, 0 replies; 200+ results
From: Mcnamara, John @ 2015-06-24 11:21 UTC (permalink / raw)
To: Neil Horman, dev
> -----Original Message-----
> From: Neil Horman [mailto:nhorman@tuxdriver.com]
> Sent: Tuesday, June 23, 2015 8:34 PM
> To: dev@dpdk.org
> Cc: Neil Horman; Mcnamara, John; thomas.monjalon@6wind.com
> Subject: [PATCH 2/2] ABI: Add some documentation
>
> People have been asking for ways to use the ABI macros, heres some docs to
> clarify their use. Included is:
Hi,
Thanks for this.
There are a few minor comments on the RST structure below.
Also, there is a conflict in the doc/guides/guidelines/index.rst file with an addition that just got merged. I just needs a rebase.
> +This file needs to be modified as follows
> +
> +.. code-block:: none
> +
> + DPDK_2.0 {
> + global:
> +
> + rte_acl_add_rules;
> + rte_acl_build;
> + rte_acl_classify;
> + rte_acl_classify_alg;
> + rte_acl_classify_scalar;
> + rte_acl_create;
> + rte_acl_dump;
> + rte_acl_find_existing;
> + rte_acl_free;
> + rte_acl_ipv4vlan_add_rules;
> + rte_acl_ipv4vlan_build;
> + rte_acl_list_dump;
> + rte_acl_reset;
> + rte_acl_reset_rules;
> + rte_acl_set_ctx_classify;
> +
> + local: *;
> + };
> +
> + DPDK_2.1 {
> + global:
> + rte_acl_create;
> +
> + } DPDK_2.0;
The last 7 lines of this verbatim section should be indented to the same level as the rest of the section. In general the code blocks should be indented at least 3 spaces to keep the various RST converters happy. That applies in a few places.
> +Note that the base name of the symbol was kept in tact, as this is
> +condusive to the macros used for versioning symbols. That is our next
> +step, mapping this new symbol name to the initial symbol name at
> +version node 2.0. Immediately after the function, we add this line of
> +code
> +
> +.. code-block:: c
> +
> + VERSION_SYMBOL(rte_acl_create, _v20, 2.0);VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
The is a duplicate macro here.
> +
> +Remembering to also add the rte_compat.h header to the requisite c file
> +where these changes are being made. The above macro instructs the
> +linker to create a new symbol rte_acl_create@DPDK_2.0, which matches
Could you enclose the symbol in RST backquotes ``rte_acl_create@DPDK_2.0`` since some of the renderers treat this as an email address! There is another one a few paragraphs down.
> +the symbol created in older builds, but now points to the above newly
> +named function. We have now mapped the origional rte_acl_create symbol
> +to the origional function
There are a few minor typos here and there.
> + };
> +
> + DPDK_2.1 {
> + global:
> + rte_acl_create;
> + } DPDK_2.0;
Same comment as above on indentation.
John.
--
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v2 08/12] mempool: allow config override on element alignment
2015-06-23 20:43 4% ` Cyril Chemparathy
@ 2015-06-23 21:21 0% ` Ananyev, Konstantin
0 siblings, 0 replies; 200+ results
From: Ananyev, Konstantin @ 2015-06-23 21:21 UTC (permalink / raw)
To: Cyril Chemparathy; +Cc: dev
> -----Original Message-----
> From: Cyril Chemparathy [mailto:cchemparathy@ezchip.com]
> Sent: Tuesday, June 23, 2015 9:43 PM
> To: Ananyev, Konstantin
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2 08/12] mempool: allow config override on element alignment
>
> On Tue, 23 Jun 2015 00:31:06 +0000
> "Ananyev, Konstantin" <konstantin.ananyev@intel.com> wrote:
>
> > > +#define RTE_MEMPOOL_ALIGN_MASK (RTE_MEMPOOL_ALIGN - 1)
> >
> > I am probably a bit late with my comments, but why not make it a
> > runtime decision then? I know we can't add a new parameter to
> > mempool_xmem_create() without ABI breakage, but we can make some
> > global variable for now, that could be setup at init time or
> > something similar.
>
> But then, a global variable that is modified by an application _is_ a
> part of the ABI, and a bad one at that.
>
> I agree with the desire to make it runtime configurable, but I think we
> should do so in the right spirit, with the appropriate interfaces, and
> when we're open to changing the ABI accordingly.
Ok, let's wait till next release then.
Konstantin
>
> Thanks
> -- Cyril.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v2 08/12] mempool: allow config override on element alignment
2015-06-23 0:31 3% ` Ananyev, Konstantin
@ 2015-06-23 20:43 4% ` Cyril Chemparathy
2015-06-23 21:21 0% ` Ananyev, Konstantin
0 siblings, 1 reply; 200+ results
From: Cyril Chemparathy @ 2015-06-23 20:43 UTC (permalink / raw)
To: Ananyev, Konstantin; +Cc: dev
On Tue, 23 Jun 2015 00:31:06 +0000
"Ananyev, Konstantin" <konstantin.ananyev@intel.com> wrote:
> > +#define RTE_MEMPOOL_ALIGN_MASK (RTE_MEMPOOL_ALIGN - 1)
>
> I am probably a bit late with my comments, but why not make it a
> runtime decision then? I know we can't add a new parameter to
> mempool_xmem_create() without ABI breakage, but we can make some
> global variable for now, that could be setup at init time or
> something similar.
But then, a global variable that is modified by an application _is_ a
part of the ABI, and a bad one at that.
I agree with the desire to make it runtime configurable, but I think we
should do so in the right spirit, with the appropriate interfaces, and
when we're open to changing the ABI accordingly.
Thanks
-- Cyril.
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH 2/2] ABI: Add some documentation
@ 2015-06-23 19:33 14% ` Neil Horman
2015-06-24 11:21 4% ` Mcnamara, John
` (2 subsequent siblings)
3 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-06-23 19:33 UTC (permalink / raw)
To: dev
People have been asking for ways to use the ABI macros, heres some docs to
clarify their use. Included is:
* An overview of what ABI is
* Details of the ABI deprecation process
* Details of the versioning macros
* Examples of their use
* Details of how to use the ABI validator
Thanks to John Mcnamara, who duplicated much of this effort at Intel while I was
working on it. Much of the introductory material was gathered and cleaned up by
him
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: john.mcnamara@intel.com
CC: thomas.monjalon@6wind.com
---
doc/guides/guidelines/index.rst | 1 +
doc/guides/guidelines/versioning.rst | 456 +++++++++++++++++++++++++++++++++++
2 files changed, 457 insertions(+)
create mode 100644 doc/guides/guidelines/versioning.rst
diff --git a/doc/guides/guidelines/index.rst b/doc/guides/guidelines/index.rst
index b2b0a92..251062e 100644
--- a/doc/guides/guidelines/index.rst
+++ b/doc/guides/guidelines/index.rst
@@ -6,3 +6,4 @@ Guidelines
:numbered:
coding_style
+ versioning
diff --git a/doc/guides/guidelines/versioning.rst b/doc/guides/guidelines/versioning.rst
new file mode 100644
index 0000000..79af924
--- /dev/null
+++ b/doc/guides/guidelines/versioning.rst
@@ -0,0 +1,456 @@
+Managing ABI updates
+====================
+
+Description
+-----------
+
+This document details some methods for handling ABI management in the DPDK.
+Note this document is not exhaustive, in that C library versioning is flexible
+allowing multiple methods to acheive various goals, but it will provide the user
+with some introductory methods
+
+General Guidelines
+------------------
+
+#. Whenever possible, ABI should be preserved
+#. The addition of symbols is generally not problematic
+#. The modification of symbols can generally be managed with versioning
+#. The removal of symbols generally is an ABI break and requires bumping of the
+ LIBABIVER macro
+
+What is an ABI
+--------------
+
+An ABI (Application Binary Interface) is the set of runtime interfaces exposed
+by a library. It is similar to an API (Application Programming Interface) but
+is the result of compilation. It is also effectively cloned when applications
+link to dynamic libraries. That is to say when an application is compiled to
+link against dynamic libraries, it is assumed that the ABI remains constant
+between the time the application is compiled/linked, and the time that it runs.
+Therefore, in the case of dynamic linking, it is critical that an ABI is
+preserved, or (when modified), done in such a way that the application is unable
+to behave improperly or in an unexpected fashion.
+
+The DPDK ABI policy
+-------------------
+
+ABI versions are set at the time of major release labeling, and the ABI may
+change multiple times, without warning, between the last release label and the
+HEAD label of the git tree.
+
+ABI versions, once released, are available until such time as their
+deprecation has been noted in the Release Notes for at least one major release
+cycle. For example consider the case where the ABI for DPDK 2.0 has been
+shipped and then a decision is made to modify it during the development of
+DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1
+release and the modification will be made available in the DPDK 2.2 release.
+
+ABI versions may be deprecated in whole or in part as needed by a given
+update.
+
+Some ABI changes may be too significant to reasonably maintain multiple
+versions. In those cases ABI's may be updated without backward compatibility
+being provided. The requirements for doing so are:
+
+#. At least 3 acknowledgments of the need to do so must be made on the
+ dpdk.org mailing list.
+
+#. A full deprecation cycle, as explained above, must be made to offer
+ downstream consumers sufficient warning of the change.
+
+#. The ``LIBABIVER`` variable in the makefile(s) where the ABI changes are
+ incorporated must be incremented in parallel with the ABI changes
+ themselves.
+
+Note that the above process for ABI deprecation should not be undertaken
+lightly. ABI stability is extremely important for downstream consumers of the
+DPDK, especially when distributed in shared object form. Every effort should
+be made to preserve the ABI whenever possible. The ABI should only be changed
+for significant reasons, such as performance enhancements. ABI breakage due to
+changes such as reorganizing public structure fields for aesthetic or
+readability purposes should be avoided.
+
+Examples of Deprecation Notices
+-------------------------------
+
+The following are some examples of ABI deprecation notices which would be
+added to the Release Notes:
+
+* The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0,
+ to be replaced with the inline function ``rte_foo()``.
+
+* The function ``rte_mbuf_grok()`` has been updated to include a new parameter
+ in version 2.0. Backwards compatibility will be maintained for this function
+ until the release of version 2.1
+
+* The members of ``struct rte_foo`` have been reorganized in release 2.0 for
+ performance reasons. Existing binary applications will have backwards
+ compatibility in release 2.0, while newly built binaries will need to
+ reference the new structure variant ``struct rte_foo2``. Compatibility will
+ be removed in release 2.2, and all applications will require updating and
+ rebuilding to the new structure at that time, which will be renamed to the
+ original ``struct rte_foo``.
+
+* Significant ABI changes are planned for the ``librte_dostuff`` library. The
+ upcoming release 2.0 will not contain these changes, but release 2.1 will,
+ and no backwards compatibility is planned due to the extensive nature of
+ these changes. Binaries using this library built prior to version 2.1 will
+ require updating and recompilation.
+
+Versioning Macros
+-----------------
+
+When a symbol is exported from a library to provide an API, it also provides a
+calling convention (ABI) that is embodied in its name, return type and
+arguments. Occasionally that function may need to change to accommodate new
+functionality or behavior. When that occurs, it is desirable to allow for
+backward compatibility for a time with older binaries that are dynamically
+linked to the DPDK.
+
+To support backward compatibility the ``lib/librte_compat/rte_compat.h``
+header file provides macros to use when updating exported functions. These
+macros are used in conjunction with the ``rte_<library>_version.map`` file for
+a given library to allow multiple versions of a symbol to exist in a shared
+library so that older binaries need not be immediately recompiled.
+
+The macros exported are:
+
+* ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding
+ unversioned symbol ``b`` to the internal function ``b_e``.
+
+
+* ``BASE_SYMBOL(b, e)``: Creates a symbol version table entry binding
+ unversioned symbol ``b`` to the internal function ``b_e``.
+
+* ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry instructing
+ the linker to bind references to symbol ``b`` to the internal symbol
+ ``b_e``.
+
+
+Examples of ABI Macro use
+-------------------------
+
+Updating a public API
+~~~~~~~~~~~~~~~~~~~~~
+
+Assume we have a function as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param)
+ {
+ ...
+ }
+
+
+Assume that struct rte_acl_ctx is a private structure, and that a developer
+wishes to enhance the acl api so that a debugging flag can be enabled on a
+per-context basis. This requires an addition to the structure (which, being
+private, is safe), but it also requries modifying the code as follows
+
+.. code-block:: c
+
+ /*
+ * Create an acl context object for apps to
+ * manipulate
+ */
+ struct rte_acl_ctx *
+ rte_acl_create(const struct rte_acl_param *param, int debug)
+ {
+ ...
+ }
+
+
+Note also that, being a public function, the header file prototype must also be
+changed, as must all the call sites, to reflect the new ABI footprint. We will
+maintain previous ABI versions that are accessible only to previously compiled
+binaries
+
+The addition of a parameter to the function is ABI breaking as the function is
+public, and existing application may use it in its current form. However, the
+compatibility macros in DPDK alow a developer to use symbol versioning so that
+multiple functions can be mapped to the same public symbol based on when an
+application was linked to it. To see how this is done, we start with the
+requisite libraries version map file. Initially the version map file for the
+acl library looks like this
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+This file needs to be modified as follows
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_create;
+ rte_acl_dump;
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+
+ } DPDK_2.0;
+
+The addition of the new block tells the linker that a new version node is
+available (DPDK_2.1), whcih contains the symbol rte_acl_create, and inherits the
+symbols from the DPDK_2.0 node. This list is directly translated into a list of
+exported symbols when DPDK is compiled as a shared library
+
+Next, we need to specify in the code which function map to the rte_acl_create
+symbol at which versions. First, at the site of the initial symbol definition,
+we need to update the function so that it is uniquely named, and not in conflict
+with the public symbol name
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param)
+ +rte_acl_create_v20(const struct rte_acl_param *param)
+ {
+ size_t sz;
+ struct rte_acl_ctx *ctx;
+ ...
+
+Note that the base name of the symbol was kept in tact, as this is condusive to
+the macros used for versioning symbols. That is our next step, mapping this new
+symbol name to the initial symbol name at version node 2.0. Immediately after
+the function, we add this line of code
+
+.. code-block:: c
+
+ VERSION_SYMBOL(rte_acl_create, _v20, 2.0);VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+Remembering to also add the rte_compat.h header to the requisite c file where
+these changes are being made. The above macro instructs the linker to create a
+new symbol rte_acl_create@DPDK_2.0, which matches the symbol created in older
+builds, but now points to the above newly named function. We have now mapped
+the origional rte_acl_create symbol to the origional function (but with a new
+name)
+
+Next, we need to create the 2.1 version of the symbol. We create a new function
+name, with a different suffix, and implement it appropriately
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ rte_acl_create_v21(const struct rte_acl_param *param, int debug);
+ {
+ struct rte_acl_ctx *ctx = rte_acl_create_v20(param);
+
+ ctx->debug = debug;
+
+ return ctx;
+ }
+
+This code serves as our new API call. Its the same as our old call, but adds
+the new parameter in place. Next we need to map this function to the symbol
+rte_acl_create@DPDK_2.1. To do this, we modify the public prototype of the call
+in the header file, adding the macro there to inform all including applications,
+that on re-link, the default rte_acl_create symbol should point to this
+function. Note that we could do this by simply naming the fuction above
+rte_acl_create, and the linker would chose the most recent version tag to apply
+in the version script, but we can also do this in the header file
+
+.. code-block:: c
+
+ struct rte_acl_ctx *
+ -rte_acl_create(const struct rte_acl_param *param);
+ +rte_acl_create(const struct rte_acl_param *param, int debug);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
+header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1
+version node to it. This method is more explicit and flexible than just
+reimplementing the exact symbol name, and allows for other features (such as
+linking to the old symbol version by default, when the new ABI is to be opt-in
+for a period.
+
+Thats it, on the next shared library rebuild, there will be two versions of
+rte_acl_create, an old DPDK_2.0 version, used by previously built applications,
+and a new DPDK_2.1 version, used by future built applications.
+
+
+Deprecating part of a public API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lets assume that you've done the above update, and after a few releases have
+passed you decide you would like to retire the old version of the function.
+After having gone through the ABI deprecation annoucement process, removal is
+easy. Start by removing the symbol from the requisite version map file:
+
+.. code-block:: none
+
+ DPDK_2.0 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ - rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+ DPDK_2.1 {
+ global:
+ rte_acl_create;
+ } DPDK_2.0;
+
+
+Next remove the corresponding versioned export
+.. code-block:: c
+
+ -VERSION_SYMBOL(rte_acl_create, _v20, 2.0);
+
+
+Note that the internal function definition could also be removed, but its used
+in our example by the newer version _v21, so we leave it in place. This is a
+coding style choice.
+
+Lastly, we need to bump the LIBABIVER number for this library in the Makefile to
+indicate to applications doing dynamic linking that this is a later, and
+possibly incompatible library version:
+
+.. code-block:: c
+
+ -LIBABIVER := 1
+ +LIBABIVER := 2
+
+Deprecating an entire ABI version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+While removing a symbol from and ABI may be useful, it is often more practical
+to remove an entire version node at once. If a version node completely
+specifies an API, then removing part of it, typically makes it incomplete. In
+those cases it is better to remove the entire node
+
+To do this, start by modifying the version map file, such that all symbols from
+the node to be removed are merged into the next node in the map
+
+In the case of our map above, it would transform to look as follows
+
+.. code-block:: none
+
+ DPDK_2.1 {
+ global:
+
+ rte_acl_add_rules;
+ rte_acl_build;
+ rte_acl_classify;
+ rte_acl_classify_alg;
+ rte_acl_classify_scalar;
+ rte_acl_dump;
+ rte_acl_create
+ rte_acl_find_existing;
+ rte_acl_free;
+ rte_acl_ipv4vlan_add_rules;
+ rte_acl_ipv4vlan_build;
+ rte_acl_list_dump;
+ rte_acl_reset;
+ rte_acl_reset_rules;
+ rte_acl_set_ctx_classify;
+
+ local: *;
+ };
+
+Then any uses of BIND_DEFAULT_SYMBOL that ponited to the old node should be
+updated to point to the new version node in any header files for all affected
+symbols.
+
+.. code-block:: c
+
+ -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0);
+ +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1);
+
+Lastly, any VERSION_SYMBOL macros that point to the old version node should be
+removed, taking care to keep, where neeed old code in place to support newer
+versions of the symbol.
+
+Running the ABI Validator
+-------------------------
+
+The ``scripts`` directory in the DPDK source tree contains a utility program,
+``validate-abi.sh``, for validating the DPDK ABI based on the Linux `ABI
+Compliance Checker
+<http://ispras.linuxbase.org/index.php/ABI_compliance_checker>`_.
+
+This has a dependency on the ``abi-compliance-checker`` and ``and abi-dumper``
+utilities which can be installed via a package manager. For example::
+
+ sudo yum install abi-compliance-checker
+ sudo yum install abi-dumper
+
+The syntax of the ``validate-abi.sh`` utility is::
+
+ ./scripts/validate-abi.sh <TAG1> <TAG2> <TARGET>
+
+Where ``TAG1`` and ``TAG2`` are valid git tags on the local repo and target is
+the usual DPDK compilation target.
+
+For example to test the current committed HEAD against a previous release tag
+we could add a temporary tag and run the utility as follows::
+
+ git tag MY_TEMP_TAG
+ ./scripts/validate-abi.sh v2.0.0 MY_TEMP_TAG x86_64-native-linuxapp-gcc
+
+After the validation script completes (it can take a while since it need to
+compile both tags) it will create compatibility reports in the
+``./compat_report`` directory. Listed incompatibilities can be found as
+follows::
+
+ grep -lr Incompatible compat_reports/
--
2.1.0
^ permalink raw reply [relevance 14%]
* Re: [dpdk-dev] [PATCH v8 00/18] unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (17 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 18/18] mbuf: remove old packet type bit masks Helin Zhang
@ 2015-06-23 16:13 0% ` Ananyev, Konstantin
2015-07-02 8:45 0% ` Liu, Yong
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
19 siblings, 1 reply; 200+ results
From: Ananyev, Konstantin @ 2015-06-23 16:13 UTC (permalink / raw)
To: Zhang, Helin, dev
> -----Original Message-----
> From: Zhang, Helin
> Sent: Tuesday, June 23, 2015 2:50 AM
> To: dev@dpdk.org
> Cc: Cao, Waterman; Liang, Cunming; Liu, Jijiang; Ananyev, Konstantin; Richardson, Bruce; yongwang@vmware.com;
> olivier.matz@6wind.com; Wu, Jingjing; Zhang, Helin
> Subject: [PATCH v8 00/18] unified packet type
>
> Currently only 6 bits which are stored in ol_flags are used to indicate the
> packet types. This is not enough, as some NIC hardware can recognize quite
> a lot of packet types, e.g i40e hardware can recognize more than 150 packet
> types. Hiding those packet types hides hardware offload capabilities which
> could be quite useful for improving performance and for end users.
> So an unified packet types are needed to support all possible PMDs. A 16
> bits packet_type in mbuf structure can be changed to 32 bits and used for
> this purpose. In addition, all packet types stored in ol_flag field should
> be deleted at all, and 6 bits of ol_flags can be save as the benifit.
>
> Initially, 32 bits of packet_type can be divided into several sub fields to
> indicate different packet type information of a packet. The initial design
> is to divide those bits into fields for L2 types, L3 types, L4 types, tunnel
> types, inner L2 types, inner L3 types and inner L4 types. All PMDs should
> translate the offloaded packet types into these 7 fields of information, for
> user applications.
>
> To avoid breaking ABI compatibility, currently all the code changes for
> unified packet type are disabled at compile time by default. Users can enable
> it manually by defining the macro of RTE_NEXT_ABI. The code changes will be
> valid by default in a future release, and the old version will be deleted
> accordingly, after the ABI change process is done.
>
> Note that this patch set should be integrated after another patch set for
> '[PATCH v3 0/7] support i40e QinQ stripping and insertion', to clearly solve
> the conflict during integration. As both patch sets modified 'struct rte_mbuf',
> and the final layout of the 'struct rte_mbuf' is key to vectorized ixgbe PMD.
>
> v2 changes:
> * Enlarged the packet_type field from 16 bits to 32 bits.
> * Redefined the packet type sub-fields.
> * Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
> * Used redefined packet types and enlarged packet_type field for all PMDs
> and corresponding applications.
> * Removed changes in bond and its relevant application, as there is no need
> at all according to the recent bond changes.
>
> v3 changes:
> * Put the mbuf layout changes into a single patch.
> * Put vector ixgbe changes right after mbuf changes.
> * Disabled vector ixgbe PMD by default, as mbuf layout changed, and then
> re-enabled it after vector ixgbe PMD updated.
> * Put the definitions of unified packet type into a single patch.
> * Minor bug fixes and enhancements in l3fwd example.
>
> v4 changes:
> * Added detailed description of each packet types.
> * Supported unified packet type of fm10k.
> * Added printing logs of packet types of each received packet for rxonly
> mode in testpmd.
> * Removed several useless code lines which block packet type unification from
> app/test/packet_burst_generator.c.
>
> v5 changes:
> * Added more detailed description for each packet types, together with examples.
> * Rolled back the macro definitions of RX packet flags, for ABI compitability.
>
> v6 changes:
> * Disabled the code changes for unified packet type by default, to
> avoid breaking ABI compatibility.
>
> v7 changes:
> * Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
> * Integrated with patch set for '[PATCH v3 0/7] support i40e QinQ stripping
> and insertion', to clearly solve the conflicts during merging.
>
> v8 changes:
> * Moved the field of 'vlan_tci_outer' in 'struct rte_mbuf' to the end of the 1st
> cache line, to avoid breaking any vectorized PMD storing, as fields of
> 'packet_type, pkt_len, data_len, vlan_tci, rss' should be in an contiguous 128
> bits.
>
> Helin Zhang (18):
> mbuf: redefine packet_type in rte_mbuf
> ixgbe: support unified packet type in vectorized PMD
> mbuf: add definitions of unified packet types
> e1000: replace bit mask based packet type with unified packet type
> ixgbe: replace bit mask based packet type with unified packet type
> i40e: replace bit mask based packet type with unified packet type
> enic: replace bit mask based packet type with unified packet type
> vmxnet3: replace bit mask based packet type with unified packet type
> fm10k: replace bit mask based packet type with unified packet type
> app/test-pipeline: replace bit mask based packet type with unified
> packet type
> app/testpmd: replace bit mask based packet type with unified packet
> type
> app/test: Remove useless code
> examples/ip_fragmentation: replace bit mask based packet type with
> unified packet type
> examples/ip_reassembly: replace bit mask based packet type with
> unified packet type
> examples/l3fwd-acl: replace bit mask based packet type with unified
> packet type
> examples/l3fwd-power: replace bit mask based packet type with unified
> packet type
> examples/l3fwd: replace bit mask based packet type with unified packet
> type
> mbuf: remove old packet type bit masks
>
> app/test-pipeline/pipeline_hash.c | 13 +
> app/test-pmd/csumonly.c | 14 +
> app/test-pmd/rxonly.c | 183 +++++++
> app/test/packet_burst_generator.c | 6 +-
> drivers/net/e1000/igb_rxtx.c | 102 ++++
> drivers/net/enic/enic_main.c | 26 +
> drivers/net/fm10k/fm10k_rxtx.c | 27 ++
> drivers/net/i40e/i40e_rxtx.c | 528 +++++++++++++++++++++
> drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++
> drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 ++-
> drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 +
> examples/ip_fragmentation/main.c | 9 +
> examples/ip_reassembly/main.c | 9 +
> examples/l3fwd-acl/main.c | 29 +-
> examples/l3fwd-power/main.c | 8 +
> examples/l3fwd/main.c | 123 ++++-
> .../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 +
> lib/librte_mbuf/rte_mbuf.c | 4 +
> lib/librte_mbuf/rte_mbuf.h | 517 ++++++++++++++++++++
> 19 files changed, 1837 insertions(+), 13 deletions(-)
>
> --
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 1.9.3
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port stats and config option
2015-06-23 14:54 0% ` Thomas Monjalon
@ 2015-06-23 15:21 0% ` Dumitrescu, Cristian
0 siblings, 0 replies; 200+ results
From: Dumitrescu, Cristian @ 2015-06-23 15:21 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Tuesday, June 23, 2015 3:55 PM
> To: Dumitrescu, Cristian
> Cc: Gajdzica, MaciejX T; dev@dpdk.org; nhorman@tuxdriver.com
> Subject: Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port
> stats and config option
>
> 2015-06-23 14:30, Dumitrescu, Cristian:
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> > > 2015-06-19 11:41, Maciej Gajdzica:
> > > > /** Input port interface defining the input port operation */
> > > > struct rte_port_in_ops {
> > > > rte_port_in_op_create f_create; /**< Create */
> > > > rte_port_in_op_free f_free; /**< Free */
> > > > rte_port_in_op_rx f_rx; /**< Packet RX (packet burst) */
> > > > + rte_port_in_op_stats_read f_stats; /**< Stats */
> > > > };
> > >
> > > Isn't it breaking an ABI?
> >
> > This is simply adding a field at the end of the API structure. This structure is
> instantiated per each port type and its role is very similar to a driver ops
> structure, for example:
> >
> > in file "rte_port_ethdev.h": extern struct rte_port_out_ops
> rte_port_ethdev_writer_ops;
> > in file "rte_port_ring.h": extern struct rte_port_out_ops
> rte_port_ring_writer_nodrop_ops;
> >
> > Typically, instances of these structures are only referenced through
> pointers by application code (and other libraries, like librte_pipeline), so code
> that is not aware of this last field in the structure will still continue to work.
> >
> > The only case I see possible when code will break is if somebody would
> create an array of such structures, but I think this is not a realistic scenario.
> Instances of this structure are infrequent: once per port type in librte_port,
> and new instances are only created when the user wants to create new port
> type. Basically, instances of this structure are created in isolation and not in
> bulk (arrays).
>
> Why wouldn't it be a problem even for single instance?
> If the application allocates one with old sizeof and the lib is trying to write
> in the new field, there can be a problem, no?
>
The only case when the application is required to create a new instance of this structure is when the application is defining a new port type (unlikely). In this case, the application using the old structure layout is not aware about the statistics functionality, so it will not invoke it, so the library will not attempt to read the f_stats structure field. Since this field is immediately after the old structure layout, the other fields in the structure are not disturbed, so the application works just fine.
The only case when the application using the old structure layout is impacted is when the position of the old structure fields changes, and this can only happen when an array of such structures is created. To my earlier point, this is not realistic, as instances of this structure are created in isolation (single instance, not array of instances) and are accessed through pointers.
> Maybe Neil has an opinion?
>
> > Due to this, I do not see this as breaking the API. I think this is the most it
> could be done to minimize the effect on the ABI will still adding new
> functionality. Please let me know what you think.
> >
> > >
> > > > struct rte_port_out_ops {
> > > > - rte_port_out_op_create f_create; /**< Create */
> > > > - rte_port_out_op_free f_free; /**< Free */
> > > > - rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> > > > - rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst)
> > > */
> > > > - rte_port_out_op_flush f_flush; /**< Flush */
> > > > + rte_port_out_op_create f_create; /**< Create */
> > > > + rte_port_out_op_free f_free; /**< Free */
> > > > + rte_port_out_op_tx f_tx; /**< Packet
> > > TX (single packet) */
> > > > + rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX
> > > (packet burst) */
> > > > + rte_port_out_op_flush f_flush; /**< Flush */
> > >
> > > What is the goal of this change? Breaking the alignment?
> >
> > Shall we submit a new patch revision to fix the alignment of the
> comments?
>
> Yes using spaces for alignment would be better.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v7 0/4] User-space Ethtool
2015-06-18 12:47 0% ` Wang, Liang-min
@ 2015-06-23 15:19 0% ` Wang, Liang-min
0 siblings, 0 replies; 200+ results
From: Wang, Liang-min @ 2015-06-23 15:19 UTC (permalink / raw)
To: 'Stephen Hemminger'; +Cc: 'dev@dpdk.org'
Stephen,
From: Wang, Liang-min
Sent: Thursday, June 18, 2015 8:47 AM
To: Stephen Hemminger
Cc: dev@dpdk.org
Subject: RE: [dpdk-dev] [PATCH v7 0/4] User-space Ethtool
>>I agree with having a more complete API, but have some nits to pick.
>>Could the API be more abstract to reduce ABI issues in future?
>Which API? Are you referring to the APIs over ethdev level, or something else?
>More abstract on input/output data structure definition or else? Could you be more specific?
>>I know choosing names is hard, but as a Linux developer ethtool has a very specific meaning to me.
>>This API encompasses things broader than Linux ethtool and has different semantics therefore
>>not sure having something in DPDK with same name is really a good idea.
>>
>>It would be better to call it something else like netdev_?? Or dpnet_??
>Just to clarify the naming suggestion, in this patch, the prefix “ethtool” only appears on example and on this patch description.
>Are you suggesting changing the name over example/l2fwd-ethtool or on this patch description, or may be both?
Have not heard your feedback on last request?
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port stats and config option
2015-06-23 13:55 3% ` Thomas Monjalon
2015-06-23 14:30 3% ` Dumitrescu, Cristian
@ 2015-06-23 15:16 3% ` Neil Horman
1 sibling, 0 replies; 200+ results
From: Neil Horman @ 2015-06-23 15:16 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Tue, Jun 23, 2015 at 03:55:25PM +0200, Thomas Monjalon wrote:
> 2015-06-19 11:41, Maciej Gajdzica:
> > /** Input port interface defining the input port operation */
> > struct rte_port_in_ops {
> > rte_port_in_op_create f_create; /**< Create */
> > rte_port_in_op_free f_free; /**< Free */
> > rte_port_in_op_rx f_rx; /**< Packet RX (packet burst) */
> > + rte_port_in_op_stats_read f_stats; /**< Stats */
> > };
>
> Isn't it breaking an ABI?
>
This is an interesting question. Strictly speaking, yes it breaks ABI because
we're adding space, and if older applications statically allocate this
structure, it will be smaller than the port library expects, potentially
scribbling over someone elses memory. That said, I'm not sure this structure is
meant to be accessed outside of the library. If it isn't, then we can feel
comfortable that no one is going to access the data structure from code that was
compiled out of sync with the defining library.
The implication if thats true of course is that we should make this structure
opaque outside of the library with a structure prototype and move its definition
into the library private namespace, but I'm fine with doing that at a later date
if the intention is not to have applications touch this structure.
Regards
Neil
> > struct rte_port_out_ops {
> > - rte_port_out_op_create f_create; /**< Create */
> > - rte_port_out_op_free f_free; /**< Free */
> > - rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> > - rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst) */
> > - rte_port_out_op_flush f_flush; /**< Flush */
> > + rte_port_out_op_create f_create; /**< Create */
> > + rte_port_out_op_free f_free; /**< Free */
> > + rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> > + rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst) */
> > + rte_port_out_op_flush f_flush; /**< Flush */
>
> What is the goal of this change? Breaking the alignment?
>
> > + rte_port_out_op_stats_read f_stats; /**< Stats */
>
>
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port stats and config option
2015-06-23 14:30 3% ` Dumitrescu, Cristian
@ 2015-06-23 14:54 0% ` Thomas Monjalon
2015-06-23 15:21 0% ` Dumitrescu, Cristian
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-23 14:54 UTC (permalink / raw)
To: Dumitrescu, Cristian; +Cc: dev
2015-06-23 14:30, Dumitrescu, Cristian:
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> > 2015-06-19 11:41, Maciej Gajdzica:
> > > /** Input port interface defining the input port operation */
> > > struct rte_port_in_ops {
> > > rte_port_in_op_create f_create; /**< Create */
> > > rte_port_in_op_free f_free; /**< Free */
> > > rte_port_in_op_rx f_rx; /**< Packet RX (packet burst) */
> > > + rte_port_in_op_stats_read f_stats; /**< Stats */
> > > };
> >
> > Isn't it breaking an ABI?
>
> This is simply adding a field at the end of the API structure. This structure is instantiated per each port type and its role is very similar to a driver ops structure, for example:
>
> in file "rte_port_ethdev.h": extern struct rte_port_out_ops rte_port_ethdev_writer_ops;
> in file "rte_port_ring.h": extern struct rte_port_out_ops rte_port_ring_writer_nodrop_ops;
>
> Typically, instances of these structures are only referenced through pointers by application code (and other libraries, like librte_pipeline), so code that is not aware of this last field in the structure will still continue to work.
>
> The only case I see possible when code will break is if somebody would create an array of such structures, but I think this is not a realistic scenario. Instances of this structure are infrequent: once per port type in librte_port, and new instances are only created when the user wants to create new port type. Basically, instances of this structure are created in isolation and not in bulk (arrays).
Why wouldn't it be a problem even for single instance?
If the application allocates one with old sizeof and the lib is trying to write
in the new field, there can be a problem, no?
Maybe Neil has an opinion?
> Due to this, I do not see this as breaking the API. I think this is the most it could be done to minimize the effect on the ABI will still adding new functionality. Please let me know what you think.
>
> >
> > > struct rte_port_out_ops {
> > > - rte_port_out_op_create f_create; /**< Create */
> > > - rte_port_out_op_free f_free; /**< Free */
> > > - rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> > > - rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst)
> > */
> > > - rte_port_out_op_flush f_flush; /**< Flush */
> > > + rte_port_out_op_create f_create; /**< Create */
> > > + rte_port_out_op_free f_free; /**< Free */
> > > + rte_port_out_op_tx f_tx; /**< Packet
> > TX (single packet) */
> > > + rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX
> > (packet burst) */
> > > + rte_port_out_op_flush f_flush; /**< Flush */
> >
> > What is the goal of this change? Breaking the alignment?
>
> Shall we submit a new patch revision to fix the alignment of the comments?
Yes using spaces for alignment would be better.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port stats and config option
2015-06-23 13:55 3% ` Thomas Monjalon
@ 2015-06-23 14:30 3% ` Dumitrescu, Cristian
2015-06-23 14:54 0% ` Thomas Monjalon
2015-06-23 15:16 3% ` Neil Horman
1 sibling, 1 reply; 200+ results
From: Dumitrescu, Cristian @ 2015-06-23 14:30 UTC (permalink / raw)
To: Thomas Monjalon, Gajdzica, MaciejX T; +Cc: dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> Sent: Tuesday, June 23, 2015 2:55 PM
> To: Gajdzica, MaciejX T
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port
> stats and config option
>
> 2015-06-19 11:41, Maciej Gajdzica:
> > /** Input port interface defining the input port operation */
> > struct rte_port_in_ops {
> > rte_port_in_op_create f_create; /**< Create */
> > rte_port_in_op_free f_free; /**< Free */
> > rte_port_in_op_rx f_rx; /**< Packet RX (packet burst) */
> > + rte_port_in_op_stats_read f_stats; /**< Stats */
> > };
>
> Isn't it breaking an ABI?
This is simply adding a field at the end of the API structure. This structure is instantiated per each port type and its role is very similar to a driver ops structure, for example:
in file "rte_port_ethdev.h": extern struct rte_port_out_ops rte_port_ethdev_writer_ops;
in file "rte_port_ring.h": extern struct rte_port_out_ops rte_port_ring_writer_nodrop_ops;
Typically, instances of these structures are only referenced through pointers by application code (and other libraries, like librte_pipeline), so code that is not aware of this last field in the structure will still continue to work.
The only case I see possible when code will break is if somebody would create an array of such structures, but I think this is not a realistic scenario. Instances of this structure are infrequent: once per port type in librte_port, and new instances are only created when the user wants to create new port type. Basically, instances of this structure are created in isolation and not in bulk (arrays).
Due to this, I do not see this as breaking the API. I think this is the most it could be done to minimize the effect on the ABI will still adding new functionality. Please let me know what you think.
>
> > struct rte_port_out_ops {
> > - rte_port_out_op_create f_create; /**< Create */
> > - rte_port_out_op_free f_free; /**< Free */
> > - rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> > - rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst)
> */
> > - rte_port_out_op_flush f_flush; /**< Flush */
> > + rte_port_out_op_create f_create; /**< Create */
> > + rte_port_out_op_free f_free; /**< Free */
> > + rte_port_out_op_tx f_tx; /**< Packet
> TX (single packet) */
> > + rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX
> (packet burst) */
> > + rte_port_out_op_flush f_flush; /**< Flush */
>
> What is the goal of this change? Breaking the alignment?
Shall we submit a new patch revision to fix the alignment of the comments?
>
> > + rte_port_out_op_stats_read f_stats; /**< Stats */
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v5 01/13] port: added structures for port stats and config option
@ 2015-06-23 13:55 3% ` Thomas Monjalon
2015-06-23 14:30 3% ` Dumitrescu, Cristian
2015-06-23 15:16 3% ` Neil Horman
0 siblings, 2 replies; 200+ results
From: Thomas Monjalon @ 2015-06-23 13:55 UTC (permalink / raw)
To: Maciej Gajdzica; +Cc: dev
2015-06-19 11:41, Maciej Gajdzica:
> /** Input port interface defining the input port operation */
> struct rte_port_in_ops {
> rte_port_in_op_create f_create; /**< Create */
> rte_port_in_op_free f_free; /**< Free */
> rte_port_in_op_rx f_rx; /**< Packet RX (packet burst) */
> + rte_port_in_op_stats_read f_stats; /**< Stats */
> };
Isn't it breaking an ABI?
> struct rte_port_out_ops {
> - rte_port_out_op_create f_create; /**< Create */
> - rte_port_out_op_free f_free; /**< Free */
> - rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> - rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst) */
> - rte_port_out_op_flush f_flush; /**< Flush */
> + rte_port_out_op_create f_create; /**< Create */
> + rte_port_out_op_free f_free; /**< Free */
> + rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */
> + rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst) */
> + rte_port_out_op_flush f_flush; /**< Flush */
What is the goal of this change? Breaking the alignment?
> + rte_port_out_op_stats_read f_stats; /**< Stats */
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 18/18] mbuf: remove old packet type bit masks
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (16 preceding siblings ...)
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 17/18] examples/l3fwd: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 16:13 0% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Ananyev, Konstantin
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
As unified packet types are used instead, those old bit masks and
the relevant macros for packet type indication need to be removed.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_mbuf/rte_mbuf.c | 4 ++++
lib/librte_mbuf/rte_mbuf.h | 4 ++++
2 files changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
* Redefined the bit masks for packet RX offload flags.
v5 changes:
* Rolled back the bit masks of RX flags, for ABI compatibility.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index f506517..4320dd4 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -251,14 +251,18 @@ const char *rte_get_rx_ol_flag_name(uint64_t mask)
/* case PKT_RX_HBUF_OVERFLOW: return "PKT_RX_HBUF_OVERFLOW"; */
/* case PKT_RX_RECIP_ERR: return "PKT_RX_RECIP_ERR"; */
/* case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; */
+#ifndef RTE_NEXT_ABI
case PKT_RX_IPV4_HDR: return "PKT_RX_IPV4_HDR";
case PKT_RX_IPV4_HDR_EXT: return "PKT_RX_IPV4_HDR_EXT";
case PKT_RX_IPV6_HDR: return "PKT_RX_IPV6_HDR";
case PKT_RX_IPV6_HDR_EXT: return "PKT_RX_IPV6_HDR_EXT";
+#endif /* RTE_NEXT_ABI */
case PKT_RX_IEEE1588_PTP: return "PKT_RX_IEEE1588_PTP";
case PKT_RX_IEEE1588_TMST: return "PKT_RX_IEEE1588_TMST";
+#ifndef RTE_NEXT_ABI
case PKT_RX_TUNNEL_IPV4_HDR: return "PKT_RX_TUNNEL_IPV4_HDR";
case PKT_RX_TUNNEL_IPV6_HDR: return "PKT_RX_TUNNEL_IPV6_HDR";
+#endif /* RTE_NEXT_ABI */
default: return NULL;
}
}
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 0ee0c55..74a7f41 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -91,14 +91,18 @@ extern "C" {
#define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer overflow. */
#define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing error. */
#define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */
+#ifndef RTE_NEXT_ABI
#define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 header. */
#define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with extended IPv4 header. */
#define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 header. */
#define PKT_RX_IPV6_HDR_EXT (1ULL << 8) /**< RX packet with extended IPv6 header. */
+#endif /* RTE_NEXT_ABI */
#define PKT_RX_IEEE1588_PTP (1ULL << 9) /**< RX IEEE1588 L2 Ethernet PT Packet. */
#define PKT_RX_IEEE1588_TMST (1ULL << 10) /**< RX IEEE1588 L2/L4 timestamped packet.*/
+#ifndef RTE_NEXT_ABI
#define PKT_RX_TUNNEL_IPV4_HDR (1ULL << 11) /**< RX tunnel packet with IPv4 header.*/
#define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet with IPv6 header. */
+#endif /* RTE_NEXT_ABI */
#define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR match. */
#define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported if FDIR match. */
#define PKT_RX_QINQ_PKT (1ULL << 15) /**< RX packet with double VLAN stripped. */
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 17/18] examples/l3fwd: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (15 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 16/18] examples/l3fwd-power: " Helin Zhang
@ 2015-06-23 1:50 3% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 18/18] mbuf: remove old packet type bit masks Helin Zhang
` (2 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd/main.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 120 insertions(+), 3 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v3 changes:
* Minor bug fixes and enhancements.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 7e4bbfd..eff9580 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -948,7 +948,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
/* Handle IPv4 headers.*/
ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(m, unsigned char *) +
sizeof(struct ether_hdr));
@@ -979,8 +983,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
} else {
+#endif
/* Handle IPv6 headers.*/
struct ipv6_hdr *ipv6_hdr;
@@ -999,8 +1006,13 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
+#ifdef RTE_NEXT_ABI
+ } else
+ /* Free the mbuf that contains non-IPV4/IPV6 packet */
+ rte_pktmbuf_free(m);
+#else
}
-
+#endif
}
#ifdef DO_RFC_1812_CHECKS
@@ -1024,12 +1036,19 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
* to BAD_PORT value.
*/
static inline __attribute__((always_inline)) void
+#ifdef RTE_NEXT_ABI
+rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype)
+#else
rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t flags)
+#endif
{
uint8_t ihl;
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(ptype)) {
+#else
if ((flags & PKT_RX_IPV4_HDR) != 0) {
-
+#endif
ihl = ipv4_hdr->version_ihl - IPV4_MIN_VER_IHL;
ipv4_hdr->time_to_live--;
@@ -1059,11 +1078,19 @@ get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
struct ipv6_hdr *ipv6_hdr;
struct ether_hdr *eth_hdr;
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
if (pkt->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
if (rte_lpm_lookup(qconf->ipv4_lookup_struct, dst_ipv4,
&next_hop) != 0)
next_hop = portid;
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (pkt->ol_flags & PKT_RX_IPV6_HDR) {
+#endif
eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1);
if (rte_lpm6_lookup(qconf->ipv6_lookup_struct,
@@ -1097,12 +1124,52 @@ process_packet(struct lcore_conf *qconf, struct rte_mbuf *pkt,
ve = val_eth[dp];
dst_port[0] = dp;
+#ifdef RTE_NEXT_ABI
+ rfc1812_process(ipv4_hdr, dst_port, pkt->packet_type);
+#else
rfc1812_process(ipv4_hdr, dst_port, pkt->ol_flags);
+#endif
te = _mm_blend_epi16(te, ve, MASK_ETH);
_mm_store_si128((__m128i *)eth_hdr, te);
}
+#ifdef RTE_NEXT_ABI
+/*
+ * Read packet_type and destination IPV4 addresses from 4 mbufs.
+ */
+static inline void
+processx4_step1(struct rte_mbuf *pkt[FWDSTEP],
+ __m128i *dip,
+ uint32_t *ipv4_flag)
+{
+ struct ipv4_hdr *ipv4_hdr;
+ struct ether_hdr *eth_hdr;
+ uint32_t x0, x1, x2, x3;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[0], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x0 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] = pkt[0]->packet_type & RTE_PTYPE_L3_IPV4;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[1], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x1 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[1]->packet_type;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[2], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x2 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[2]->packet_type;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[3], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x3 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[3]->packet_type;
+
+ dip[0] = _mm_set_epi32(x3, x2, x1, x0);
+}
+#else /* RTE_NEXT_ABI */
/*
* Read ol_flags and destination IPV4 addresses from 4 mbufs.
*/
@@ -1135,14 +1202,24 @@ processx4_step1(struct rte_mbuf *pkt[FWDSTEP], __m128i *dip, uint32_t *flag)
dip[0] = _mm_set_epi32(x3, x2, x1, x0);
}
+#endif /* RTE_NEXT_ABI */
/*
* Lookup into LPM for destination port.
* If lookup fails, use incoming port (portid) as destination port.
*/
static inline void
+#ifdef RTE_NEXT_ABI
+processx4_step2(const struct lcore_conf *qconf,
+ __m128i dip,
+ uint32_t ipv4_flag,
+ uint8_t portid,
+ struct rte_mbuf *pkt[FWDSTEP],
+ uint16_t dprt[FWDSTEP])
+#else
processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag,
uint8_t portid, struct rte_mbuf *pkt[FWDSTEP], uint16_t dprt[FWDSTEP])
+#endif /* RTE_NEXT_ABI */
{
rte_xmm_t dst;
const __m128i bswap_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11,
@@ -1152,7 +1229,11 @@ processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag,
dip = _mm_shuffle_epi8(dip, bswap_mask);
/* if all 4 packets are IPV4. */
+#ifdef RTE_NEXT_ABI
+ if (likely(ipv4_flag)) {
+#else
if (likely(flag != 0)) {
+#endif
rte_lpm_lookupx4(qconf->ipv4_lookup_struct, dip, dprt, portid);
} else {
dst.x = dip;
@@ -1202,6 +1283,16 @@ processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
_mm_store_si128(p[2], te[2]);
_mm_store_si128(p[3], te[3]);
+#ifdef RTE_NEXT_ABI
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1),
+ &dst_port[0], pkt[0]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1),
+ &dst_port[1], pkt[1]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[2] + 1),
+ &dst_port[2], pkt[2]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1),
+ &dst_port[3], pkt[3]->packet_type);
+#else /* RTE_NEXT_ABI */
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1),
&dst_port[0], pkt[0]->ol_flags);
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1),
@@ -1210,6 +1301,7 @@ processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
&dst_port[2], pkt[2]->ol_flags);
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1),
&dst_port[3], pkt[3]->ol_flags);
+#endif /* RTE_NEXT_ABI */
}
/*
@@ -1396,7 +1488,11 @@ main_loop(__attribute__((unused)) void *dummy)
uint16_t *lp;
uint16_t dst_port[MAX_PKT_BURST];
__m128i dip[MAX_PKT_BURST / FWDSTEP];
+#ifdef RTE_NEXT_ABI
+ uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP];
+#else
uint32_t flag[MAX_PKT_BURST / FWDSTEP];
+#endif
uint16_t pnum[MAX_PKT_BURST + 1];
#endif
@@ -1466,6 +1562,18 @@ main_loop(__attribute__((unused)) void *dummy)
*/
int32_t n = RTE_ALIGN_FLOOR(nb_rx, 4);
for (j = 0; j < n ; j+=4) {
+#ifdef RTE_NEXT_ABI
+ uint32_t pkt_type =
+ pkts_burst[j]->packet_type &
+ pkts_burst[j+1]->packet_type &
+ pkts_burst[j+2]->packet_type &
+ pkts_burst[j+3]->packet_type;
+ if (pkt_type & RTE_PTYPE_L3_IPV4) {
+ simple_ipv4_fwd_4pkts(
+ &pkts_burst[j], portid, qconf);
+ } else if (pkt_type &
+ RTE_PTYPE_L3_IPV6) {
+#else /* RTE_NEXT_ABI */
uint32_t ol_flag = pkts_burst[j]->ol_flags
& pkts_burst[j+1]->ol_flags
& pkts_burst[j+2]->ol_flags
@@ -1474,6 +1582,7 @@ main_loop(__attribute__((unused)) void *dummy)
simple_ipv4_fwd_4pkts(&pkts_burst[j],
portid, qconf);
} else if (ol_flag & PKT_RX_IPV6_HDR) {
+#endif /* RTE_NEXT_ABI */
simple_ipv6_fwd_4pkts(&pkts_burst[j],
portid, qconf);
} else {
@@ -1498,13 +1607,21 @@ main_loop(__attribute__((unused)) void *dummy)
for (j = 0; j != k; j += FWDSTEP) {
processx4_step1(&pkts_burst[j],
&dip[j / FWDSTEP],
+#ifdef RTE_NEXT_ABI
+ &ipv4_flag[j / FWDSTEP]);
+#else
&flag[j / FWDSTEP]);
+#endif
}
k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP);
for (j = 0; j != k; j += FWDSTEP) {
processx4_step2(qconf, dip[j / FWDSTEP],
+#ifdef RTE_NEXT_ABI
+ ipv4_flag[j / FWDSTEP], portid,
+#else
flag[j / FWDSTEP], portid,
+#endif
&pkts_burst[j], &dst_port[j]);
}
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 16/18] examples/l3fwd-power: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (14 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 15/18] examples/l3fwd-acl: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 17/18] examples/l3fwd: " Helin Zhang
` (3 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd-power/main.c | 8 ++++++++
1 file changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index 6057059..705188f 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -635,7 +635,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
/* Handle IPv4 headers.*/
ipv4_hdr =
(struct ipv4_hdr *)(rte_pktmbuf_mtod(m, unsigned char*)
@@ -670,8 +674,12 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
}
else {
+#endif
/* Handle IPv6 headers.*/
#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
struct ipv6_hdr *ipv6_hdr;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 15/18] examples/l3fwd-acl: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (13 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 14/18] examples/ip_reassembly: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 16/18] examples/l3fwd-power: " Helin Zhang
` (4 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd-acl/main.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c
index a5d4f25..78b6df2 100644
--- a/examples/l3fwd-acl/main.c
+++ b/examples/l3fwd-acl/main.c
@@ -645,10 +645,13 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
struct ipv4_hdr *ipv4_hdr;
struct rte_mbuf *pkt = pkts_in[index];
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR);
if (type == PKT_RX_IPV4_HDR) {
-
+#endif
ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(pkt,
unsigned char *) + sizeof(struct ether_hdr));
@@ -667,9 +670,11 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
/* Not a valid IPv4 packet */
rte_pktmbuf_free(pkt);
}
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (type == PKT_RX_IPV6_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
acl->m_ipv6[(acl->num_ipv6)++] = pkt;
@@ -687,17 +692,22 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
{
struct rte_mbuf *pkt = pkts_in[index];
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR);
if (type == PKT_RX_IPV4_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
acl->m_ipv4[(acl->num_ipv4)++] = pkt;
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (type == PKT_RX_IPV6_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
acl->m_ipv6[(acl->num_ipv6)++] = pkt;
@@ -745,10 +755,17 @@ send_one_packet(struct rte_mbuf *m, uint32_t res)
/* in the ACL list, drop it */
#ifdef L3FWDACL_DEBUG
if ((res & ACL_DENY_SIGNATURE) != 0) {
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type))
+ dump_acl4_rule(m, res);
+ else if (RTE_ETH_IS_IPV6_HDR(m->packet_type))
+ dump_acl6_rule(m, res);
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR)
dump_acl4_rule(m, res);
else
dump_acl6_rule(m, res);
+#endif /* RTE_NEXT_ABI */
}
#endif
rte_pktmbuf_free(m);
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 14/18] examples/ip_reassembly: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (12 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 15/18] examples/l3fwd-acl: " Helin Zhang
` (5 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/ip_reassembly/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c
index 9ecb6f9..f1c47ad 100644
--- a/examples/ip_reassembly/main.c
+++ b/examples/ip_reassembly/main.c
@@ -356,7 +356,11 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue,
dst_port = portid;
/* if packet is IPv4 */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & (PKT_RX_IPV4_HDR)) {
+#endif
struct ipv4_hdr *ip_hdr;
uint32_t ip_dst;
@@ -396,9 +400,14 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue,
}
eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4);
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ /* if packet is IPv6 */
+#else
}
/* if packet is IPv6 */
else if (m->ol_flags & (PKT_RX_IPV6_HDR | PKT_RX_IPV6_HDR_EXT)) {
+#endif
struct ipv6_extension_fragment *frag_hdr;
struct ipv6_hdr *ip_hdr;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (11 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 12/18] app/test: Remove useless code Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 14/18] examples/ip_reassembly: " Helin Zhang
` (6 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/ip_fragmentation/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 0922ba6..b71d05f 100644
--- a/examples/ip_fragmentation/main.c
+++ b/examples/ip_fragmentation/main.c
@@ -283,7 +283,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
len = qconf->tx_mbufs[port_out].len;
/* if this is an IPv4 packet */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
struct ipv4_hdr *ip_hdr;
uint32_t ip_dst;
/* Read the lookup key (i.e. ip_dst) from the input packet */
@@ -317,9 +321,14 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
if (unlikely (len2 < 0))
return;
}
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ /* if this is an IPv6 packet */
+#else
}
/* if this is an IPv6 packet */
else if (m->ol_flags & PKT_RX_IPV6_HDR) {
+#endif
struct ipv6_hdr *ip_hdr;
ipv6 = 1;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 12/18] app/test: Remove useless code
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (10 preceding siblings ...)
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 11/18] app/testpmd: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
` (7 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
Severl useless code lines are added accidently, which blocks packet
type unification. They should be deleted at all.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
app/test/packet_burst_generator.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
v4 changes:
* Removed several useless code lines which block packet type unification.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test/packet_burst_generator.c b/app/test/packet_burst_generator.c
index b46eed7..61e6340 100644
--- a/app/test/packet_burst_generator.c
+++ b/app/test/packet_burst_generator.c
@@ -272,19 +272,21 @@ nomore_mbuf:
if (ipv4) {
pkt->vlan_tci = ETHER_TYPE_IPv4;
pkt->l3_len = sizeof(struct ipv4_hdr);
-
+#ifndef RTE_NEXT_ABI
if (vlan_enabled)
pkt->ol_flags = PKT_RX_IPV4_HDR | PKT_RX_VLAN_PKT;
else
pkt->ol_flags = PKT_RX_IPV4_HDR;
+#endif
} else {
pkt->vlan_tci = ETHER_TYPE_IPv6;
pkt->l3_len = sizeof(struct ipv6_hdr);
-
+#ifndef RTE_NEXT_ABI
if (vlan_enabled)
pkt->ol_flags = PKT_RX_IPV6_HDR | PKT_RX_VLAN_PKT;
else
pkt->ol_flags = PKT_RX_IPV6_HDR;
+#endif
}
pkts_burst[nb_pkt] = pkt;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 11/18] app/testpmd: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (9 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 10/18] app/test-pipeline: " Helin Zhang
@ 2015-06-23 1:50 3% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 12/18] app/test: Remove useless code Helin Zhang
` (8 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Jijiang Liu <jijiang.liu@intel.com>
---
app/test-pmd/csumonly.c | 14 ++++
app/test-pmd/rxonly.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 197 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v4 changes:
* Added printing logs of packet types of each received packet in rxonly mode.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
index 950ea82..fab9600 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -202,8 +202,14 @@ parse_ethernet(struct ether_hdr *eth_hdr, struct testpmd_offload_info *info)
/* Parse a vxlan header */
static void
+#ifdef RTE_NEXT_ABI
+parse_vxlan(struct udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info,
+ uint32_t pkt_type)
+#else
parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info,
uint64_t mbuf_olflags)
+#endif
{
struct ether_hdr *eth_hdr;
@@ -211,8 +217,12 @@ parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info,
* (rfc7348) or that the rx offload flag is set (i40e only
* currently) */
if (udp_hdr->dst_port != _htons(4789) &&
+#ifdef RTE_NEXT_ABI
+ RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0)
+#else
(mbuf_olflags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR)) == 0)
+#endif
return;
info->is_tunnel = 1;
@@ -549,7 +559,11 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)
struct udp_hdr *udp_hdr;
udp_hdr = (struct udp_hdr *)((char *)l3_hdr +
info.l3_len);
+#ifdef RTE_NEXT_ABI
+ parse_vxlan(udp_hdr, &info, m->packet_type);
+#else
parse_vxlan(udp_hdr, &info, m->ol_flags);
+#endif
} else if (info.l4_proto == IPPROTO_GRE) {
struct simple_gre_hdr *gre_hdr;
gre_hdr = (struct simple_gre_hdr *)
diff --git a/app/test-pmd/rxonly.c b/app/test-pmd/rxonly.c
index f6a2f84..5a30347 100644
--- a/app/test-pmd/rxonly.c
+++ b/app/test-pmd/rxonly.c
@@ -91,7 +91,11 @@ pkt_burst_receive(struct fwd_stream *fs)
uint64_t ol_flags;
uint16_t nb_rx;
uint16_t i, packet_type;
+#ifdef RTE_NEXT_ABI
+ uint16_t is_encapsulation;
+#else
uint64_t is_encapsulation;
+#endif
#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
uint64_t start_tsc;
@@ -135,8 +139,12 @@ pkt_burst_receive(struct fwd_stream *fs)
ol_flags = mb->ol_flags;
packet_type = mb->packet_type;
+#ifdef RTE_NEXT_ABI
+ is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
+#else
is_encapsulation = ol_flags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR);
+#endif
print_ether_addr(" src=", ð_hdr->s_addr);
print_ether_addr(" - dst=", ð_hdr->d_addr);
@@ -163,6 +171,177 @@ pkt_burst_receive(struct fwd_stream *fs)
if (ol_flags & PKT_RX_QINQ_PKT)
printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
mb->vlan_tci, mb->vlan_tci_outer);
+#ifdef RTE_NEXT_ABI
+ if (mb->packet_type) {
+ uint32_t ptype;
+
+ /* (outer) L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L2_MAC:
+ printf(" - (outer) L2 type: MAC");
+ break;
+ case RTE_PTYPE_L2_MAC_TIMESYNC:
+ printf(" - (outer) L2 type: MAC Timesync");
+ break;
+ case RTE_PTYPE_L2_ARP:
+ printf(" - (outer) L2 type: ARP");
+ break;
+ case RTE_PTYPE_L2_LLDP:
+ printf(" - (outer) L2 type: LLDP");
+ break;
+ default:
+ printf(" - (outer) L2 type: Unknown");
+ break;
+ }
+
+ /* (outer) L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L3_IPV4:
+ printf(" - (outer) L3 type: IPV4");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT:
+ printf(" - (outer) L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6:
+ printf(" - (outer) L3 type: IPV6");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT:
+ printf(" - (outer) L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV6_EXT_UNKNOWN");
+ break;
+ default:
+ printf(" - (outer) L3 type: Unknown");
+ break;
+ }
+
+ /* (outer) L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L4_TCP:
+ printf(" - (outer) L4 type: TCP");
+ break;
+ case RTE_PTYPE_L4_UDP:
+ printf(" - (outer) L4 type: UDP");
+ break;
+ case RTE_PTYPE_L4_FRAG:
+ printf(" - (outer) L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_L4_SCTP:
+ printf(" - (outer) L4 type: SCTP");
+ break;
+ case RTE_PTYPE_L4_ICMP:
+ printf(" - (outer) L4 type: ICMP");
+ break;
+ case RTE_PTYPE_L4_NONFRAG:
+ printf(" - (outer) L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - (outer) L4 type: Unknown");
+ break;
+ }
+
+ /* packet tunnel type */
+ ptype = mb->packet_type & RTE_PTYPE_TUNNEL_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_TUNNEL_IP:
+ printf(" - Tunnel type: IP");
+ break;
+ case RTE_PTYPE_TUNNEL_GRE:
+ printf(" - Tunnel type: GRE");
+ break;
+ case RTE_PTYPE_TUNNEL_VXLAN:
+ printf(" - Tunnel type: VXLAN");
+ break;
+ case RTE_PTYPE_TUNNEL_NVGRE:
+ printf(" - Tunnel type: NVGRE");
+ break;
+ case RTE_PTYPE_TUNNEL_GENEVE:
+ printf(" - Tunnel type: GENEVE");
+ break;
+ case RTE_PTYPE_TUNNEL_GRENAT:
+ printf(" - Tunnel type: GRENAT");
+ break;
+ default:
+ printf(" - Tunnel type: Unkown");
+ break;
+ }
+
+ /* inner L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L2_MAC:
+ printf(" - Inner L2 type: MAC");
+ break;
+ case RTE_PTYPE_INNER_L2_MAC_VLAN:
+ printf(" - Inner L2 type: MAC_VLAN");
+ break;
+ default:
+ printf(" - Inner L2 type: Unknown");
+ break;
+ }
+
+ /* inner L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_INNER_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L3_IPV4:
+ printf(" - Inner L3 type: IPV4");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT:
+ printf(" - Inner L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6:
+ printf(" - Inner L3 type: IPV6");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN:
+ printf(" - Inner L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT:
+ printf(" - Inner L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN:
+ printf(" - Inner L3 type: IPV6_EXT_UNKOWN");
+ break;
+ default:
+ printf(" - Inner L3 type: Unkown");
+ break;
+ }
+
+ /* inner L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L4_TCP:
+ printf(" - Inner L4 type: TCP");
+ break;
+ case RTE_PTYPE_INNER_L4_UDP:
+ printf(" - Inner L4 type: UDP");
+ break;
+ case RTE_PTYPE_INNER_L4_FRAG:
+ printf(" - Inner L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_INNER_L4_SCTP:
+ printf(" - Inner L4 type: SCTP");
+ break;
+ case RTE_PTYPE_INNER_L4_ICMP:
+ printf(" - Inner L4 type: ICMP");
+ break;
+ case RTE_PTYPE_INNER_L4_NONFRAG:
+ printf(" - Inner L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - Inner L4 type: Unknown");
+ break;
+ }
+ printf("\n");
+ } else
+ printf("Unknown packet type\n");
+#endif /* RTE_NEXT_ABI */
if (is_encapsulation) {
struct ipv4_hdr *ipv4_hdr;
struct ipv6_hdr *ipv6_hdr;
@@ -176,7 +355,11 @@ pkt_burst_receive(struct fwd_stream *fs)
l2_len = sizeof(struct ether_hdr);
/* Do not support ipv4 option field */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(packet_type)) {
+#else
if (ol_flags & PKT_RX_TUNNEL_IPV4_HDR) {
+#endif
l3_len = sizeof(struct ipv4_hdr);
ipv4_hdr = (struct ipv4_hdr *) (rte_pktmbuf_mtod(mb,
unsigned char *) + l2_len);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 10/18] app/test-pipeline: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (8 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 09/18] fm10k: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 11/18] app/testpmd: " Helin Zhang
` (9 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
app/test-pipeline/pipeline_hash.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test-pipeline/pipeline_hash.c b/app/test-pipeline/pipeline_hash.c
index 4598ad4..aa3f9e5 100644
--- a/app/test-pipeline/pipeline_hash.c
+++ b/app/test-pipeline/pipeline_hash.c
@@ -459,20 +459,33 @@ app_main_loop_rx_metadata(void) {
signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0);
key = RTE_MBUF_METADATA_UINT8_PTR(m, 32);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
ip_hdr = (struct ipv4_hdr *)
&m_data[sizeof(struct ether_hdr)];
ip_dst = ip_hdr->dst_addr;
k32 = (uint32_t *) key;
k32[0] = ip_dst & 0xFFFFFF00;
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
} else {
+#endif
ipv6_hdr = (struct ipv6_hdr *)
&m_data[sizeof(struct ether_hdr)];
ipv6_dst = ipv6_hdr->dst_addr;
memcpy(key, ipv6_dst, 16);
+#ifdef RTE_NEXT_ABI
+ } else
+ continue;
+#else
}
+#endif
*signature = test_hash(key, 0, 0);
}
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 09/18] fm10k: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (7 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 08/18] vmxnet3: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 10/18] app/test-pipeline: " Helin Zhang
` (10 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/fm10k/fm10k_rxtx.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
v4 changes:
* Supported unified packet type of fm10k from v4.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/fm10k/fm10k_rxtx.c b/drivers/net/fm10k/fm10k_rxtx.c
index f5d1ad0..4b00f5c 100644
--- a/drivers/net/fm10k/fm10k_rxtx.c
+++ b/drivers/net/fm10k/fm10k_rxtx.c
@@ -68,12 +68,37 @@ static inline void dump_rxd(union fm10k_rx_desc *rxd)
static inline void
rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d)
{
+#ifdef RTE_NEXT_ABI
+ static const uint32_t
+ ptype_table[FM10K_RXD_PKTTYPE_MASK >> FM10K_RXD_PKTTYPE_SHIFT]
+ __rte_cache_aligned = {
+ [FM10K_PKTTYPE_OTHER] = RTE_PTYPE_L2_MAC,
+ [FM10K_PKTTYPE_IPV4] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4,
+ [FM10K_PKTTYPE_IPV4_EX] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [FM10K_PKTTYPE_IPV6] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6,
+ [FM10K_PKTTYPE_IPV6_EX] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ };
+
+ m->packet_type = ptype_table[(d->w.pkt_info & FM10K_RXD_PKTTYPE_MASK)
+ >> FM10K_RXD_PKTTYPE_SHIFT];
+#else /* RTE_NEXT_ABI */
uint16_t ptype;
static const uint16_t pt_lut[] = { 0,
PKT_RX_IPV4_HDR, PKT_RX_IPV4_HDR_EXT,
PKT_RX_IPV6_HDR, PKT_RX_IPV6_HDR_EXT,
0, 0, 0
};
+#endif /* RTE_NEXT_ABI */
if (d->w.pkt_info & FM10K_RXD_RSSTYPE_MASK)
m->ol_flags |= PKT_RX_RSS_HASH;
@@ -97,9 +122,11 @@ rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d)
if (unlikely(d->d.staterr & FM10K_RXD_STATUS_RXE))
m->ol_flags |= PKT_RX_RECIP_ERR;
+#ifndef RTE_NEXT_ABI
ptype = (d->d.data & FM10K_RXD_PKTTYPE_MASK_L3) >>
FM10K_RXD_PKTTYPE_SHIFT;
m->ol_flags |= pt_lut[(uint8_t)ptype];
+#endif
}
uint16_t
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 07/18] enic: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (5 preceding siblings ...)
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 06/18] i40e: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 08/18] vmxnet3: " Helin Zhang
` (12 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/enic/enic_main.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 15313c2..f47e96c 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -423,7 +423,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
rx_pkt->pkt_len = bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD;
@@ -432,7 +436,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
} else {
/* Header split */
if (sop && !eop) {
@@ -445,7 +453,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
*rx_pkt_bucket = rx_pkt;
rx_pkt->pkt_len = bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
rx_pkt->ol_flags |=
@@ -457,13 +469,22 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
} else {
/* Payload */
hdr_rx_pkt = *rx_pkt_bucket;
hdr_rx_pkt->pkt_len += bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ hdr_rx_pkt->packet_type =
+ RTE_PTYPE_L3_IPV4;
+#else
hdr_rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
hdr_rx_pkt->ol_flags |=
@@ -475,7 +496,12 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ hdr_rx_pkt->packet_type =
+ RTE_PTYPE_L3_IPV6;
+#else
hdr_rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
}
}
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 08/18] vmxnet3: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (6 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 07/18] enic: " Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 09/18] fm10k: " Helin Zhang
` (11 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 ++++++++
1 file changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c b/drivers/net/vmxnet3/vmxnet3_rxtx.c
index a1eac45..25ae2f6 100644
--- a/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -649,9 +649,17 @@ vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
struct ipv4_hdr *ip = (struct ipv4_hdr *)(eth + 1);
if (((ip->version_ihl & 0xf) << 2) > (int)sizeof(struct ipv4_hdr))
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = RTE_PTYPE_L3_IPV4_EXT;
+#else
rxm->ol_flags |= PKT_RX_IPV4_HDR_EXT;
+#endif
else
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rxm->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!rcd->cnc) {
if (!rcd->ipc)
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 06/18] i40e: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (4 preceding siblings ...)
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 05/18] ixgbe: " Helin Zhang
@ 2015-06-23 1:50 3% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 07/18] enic: " Helin Zhang
` (13 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/i40e/i40e_rxtx.c | 528 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 528 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index b2e1d6d..b951da0 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -176,6 +176,514 @@ i40e_rxd_error_to_pkt_flags(uint64_t qword)
return flags;
}
+#ifdef RTE_NEXT_ABI
+/* For each value it means, datasheet of hardware can tell more details */
+static inline uint32_t
+i40e_rxd_pkt_type_mapping(uint8_t ptype)
+{
+ static const uint32_t ptype_table[UINT8_MAX] __rte_cache_aligned = {
+ /* L2 types */
+ /* [0] reserved */
+ [1] = RTE_PTYPE_L2_MAC,
+ [2] = RTE_PTYPE_L2_MAC_TIMESYNC,
+ /* [3] - [5] reserved */
+ [6] = RTE_PTYPE_L2_LLDP,
+ /* [7] - [10] reserved */
+ [11] = RTE_PTYPE_L2_ARP,
+ /* [12] - [21] reserved */
+
+ /* Non tunneled IPv4 */
+ [22] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG,
+ [23] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG,
+ [24] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP,
+ /* [25] reserved */
+ [26] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP,
+ [27] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP,
+ [28] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP,
+
+ /* IPv4 --> IPv4 */
+ [29] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [30] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [31] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [32] reserved */
+ [33] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [34] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [35] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> IPv6 */
+ [36] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [37] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [38] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [39] reserved */
+ [40] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [41] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [42] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN */
+ [43] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> IPv4 */
+ [44] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [45] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [46] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [47] reserved */
+ [48] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [49] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [50] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> IPv6 */
+ [51] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [52] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [53] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [54] reserved */
+ [55] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [56] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [57] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC */
+ [58] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */
+ [59] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [60] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [61] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [62] reserved */
+ [63] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [64] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [65] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */
+ [66] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [67] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [68] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [69] reserved */
+ [70] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [71] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [72] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN */
+ [73] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */
+ [74] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [75] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [76] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [77] reserved */
+ [78] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [79] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [80] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */
+ [81] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [82] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [83] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [84] reserved */
+ [85] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [86] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [87] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* Non tunneled IPv6 */
+ [88] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG,
+ [89] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG,
+ [90] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP,
+ /* [91] reserved */
+ [92] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP,
+ [93] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP,
+ [94] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP,
+
+ /* IPv6 --> IPv4 */
+ [95] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [96] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [97] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [98] reserved */
+ [99] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [100] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [101] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> IPv6 */
+ [102] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [103] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [104] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [105] reserved */
+ [106] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [107] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [108] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN */
+ [109] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> IPv4 */
+ [110] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [111] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [112] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [113] reserved */
+ [114] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [115] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [116] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> IPv6 */
+ [117] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [118] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [119] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [120] reserved */
+ [121] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [122] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [123] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC */
+ [124] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */
+ [125] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [126] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [127] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [128] reserved */
+ [129] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [130] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [131] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */
+ [132] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [133] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [134] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [135] reserved */
+ [136] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [137] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [138] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN */
+ [139] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */
+ [140] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [141] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [142] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [143] reserved */
+ [144] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [145] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [146] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */
+ [147] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [148] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [149] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [150] reserved */
+ [151] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [152] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [153] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* All others reserved */
+ };
+
+ return ptype_table[ptype];
+}
+#else /* RTE_NEXT_ABI */
/* Translate pkt types to pkt flags */
static inline uint64_t
i40e_rxd_ptype_to_pkt_flags(uint64_t qword)
@@ -443,6 +951,7 @@ i40e_rxd_ptype_to_pkt_flags(uint64_t qword)
return ip_ptype_map[ptype];
}
+#endif /* RTE_NEXT_ABI */
#define I40E_RX_DESC_EXT_STATUS_FLEXBH_MASK 0x03
#define I40E_RX_DESC_EXT_STATUS_FLEXBH_FD_ID 0x01
@@ -730,11 +1239,18 @@ i40e_rx_scan_hw_ring(struct i40e_rx_queue *rxq)
i40e_rxd_to_vlan_tci(mb, &rxdp[j]);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ mb->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
mb->packet_type = (uint16_t)((qword1 &
I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
mb->hash.rss = rte_le_to_cpu_32(\
rxdp[j].wb.qword0.hi_dword.rss);
@@ -971,9 +1487,15 @@ i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
i40e_rxd_to_vlan_tci(rxm, &rxd);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
rxm->packet_type = (uint16_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
rxm->hash.rss =
rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss);
@@ -1129,10 +1651,16 @@ i40e_recv_scattered_pkts(void *rx_queue,
i40e_rxd_to_vlan_tci(first_seg, &rxd);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ first_seg->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
first_seg->packet_type = (uint16_t)((qword1 &
I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
rxm->hash.rss =
rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 05/18] ixgbe: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (3 preceding siblings ...)
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 04/18] e1000: replace bit mask based packet type with unified packet type Helin Zhang
@ 2015-06-23 1:50 3% ` Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 06/18] i40e: " Helin Zhang
` (14 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet type among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Note that around 2.5% performance drop (64B) was observed of doing
4 ports (1 port per 82599 card) IO forwarding on the same SNB core.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index a211096..83a869f 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -860,6 +860,110 @@ end_of_tx:
* RX functions
*
**********************************************************************/
+#ifdef RTE_NEXT_ABI
+#define IXGBE_PACKET_TYPE_IPV4 0X01
+#define IXGBE_PACKET_TYPE_IPV4_TCP 0X11
+#define IXGBE_PACKET_TYPE_IPV4_UDP 0X21
+#define IXGBE_PACKET_TYPE_IPV4_SCTP 0X41
+#define IXGBE_PACKET_TYPE_IPV4_EXT 0X03
+#define IXGBE_PACKET_TYPE_IPV4_EXT_SCTP 0X43
+#define IXGBE_PACKET_TYPE_IPV6 0X04
+#define IXGBE_PACKET_TYPE_IPV6_TCP 0X14
+#define IXGBE_PACKET_TYPE_IPV6_UDP 0X24
+#define IXGBE_PACKET_TYPE_IPV6_EXT 0X0C
+#define IXGBE_PACKET_TYPE_IPV6_EXT_TCP 0X1C
+#define IXGBE_PACKET_TYPE_IPV6_EXT_UDP 0X2C
+#define IXGBE_PACKET_TYPE_IPV4_IPV6 0X05
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_TCP 0X15
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_UDP 0X25
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT 0X0D
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D
+#define IXGBE_PACKET_TYPE_MAX 0X80
+#define IXGBE_PACKET_TYPE_MASK 0X7F
+#define IXGBE_PACKET_TYPE_SHIFT 0X04
+static inline uint32_t
+ixgbe_rxd_pkt_info_to_pkt_type(uint16_t pkt_info)
+{
+ static const uint32_t
+ ptype_table[IXGBE_PACKET_TYPE_MAX] __rte_cache_aligned = {
+ [IXGBE_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4,
+ [IXGBE_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [IXGBE_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IXGBE_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ [IXGBE_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP,
+ [IXGBE_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP,
+ };
+ if (unlikely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF))
+ return RTE_PTYPE_UNKNOWN;
+
+ pkt_info = (pkt_info >> IXGBE_PACKET_TYPE_SHIFT) &
+ IXGBE_PACKET_TYPE_MASK;
+
+ return ptype_table[pkt_info];
+}
+
+static inline uint64_t
+ixgbe_rxd_pkt_info_to_pkt_flags(uint16_t pkt_info)
+{
+ static uint64_t ip_rss_types_map[16] __rte_cache_aligned = {
+ 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH,
+ 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH,
+ PKT_RX_RSS_HASH, 0, 0, 0,
+ 0, 0, 0, PKT_RX_FDIR,
+ };
+#ifdef RTE_LIBRTE_IEEE1588
+ static uint64_t ip_pkt_etqf_map[8] = {
+ 0, 0, 0, PKT_RX_IEEE1588_PTP,
+ 0, 0, 0, 0,
+ };
+
+ if (likely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF))
+ return ip_pkt_etqf_map[(pkt_info >> 4) & 0X07] |
+ ip_rss_types_map[pkt_info & 0XF];
+ else
+ return ip_rss_types_map[pkt_info & 0XF];
+#else
+ return ip_rss_types_map[pkt_info & 0XF];
+#endif
+}
+#else /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
{
@@ -895,6 +999,7 @@ rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
#endif
return pkt_flags | ip_rss_types_map[hl_tp_rs & 0xF];
}
+#endif /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_status_to_pkt_flags(uint32_t rx_status)
@@ -950,7 +1055,13 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
struct rte_mbuf *mb;
uint16_t pkt_len;
uint64_t pkt_flags;
+#ifdef RTE_NEXT_ABI
+ int nb_dd;
+ uint32_t s[LOOK_AHEAD];
+ uint16_t pkt_info[LOOK_AHEAD];
+#else
int s[LOOK_AHEAD], nb_dd;
+#endif /* RTE_NEXT_ABI */
int i, j, nb_rx = 0;
@@ -973,6 +1084,12 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
for (j = LOOK_AHEAD-1; j >= 0; --j)
s[j] = rxdp[j].wb.upper.status_error;
+#ifdef RTE_NEXT_ABI
+ for (j = LOOK_AHEAD-1; j >= 0; --j)
+ pkt_info[j] = rxdp[j].wb.lower.lo_dword.
+ hs_rss.pkt_info;
+#endif /* RTE_NEXT_ABI */
+
/* Compute how many status bits were set */
nb_dd = 0;
for (j = 0; j < LOOK_AHEAD; ++j)
@@ -989,12 +1106,22 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].wb.upper.vlan);
/* convert descriptor fields to rte mbuf flags */
+#ifdef RTE_NEXT_ABI
+ pkt_flags = rx_desc_status_to_pkt_flags(s[j]);
+ pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
+ pkt_flags |=
+ ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]);
+ mb->ol_flags = pkt_flags;
+ mb->packet_type =
+ ixgbe_rxd_pkt_info_to_pkt_type(pkt_info[j]);
+#else /* RTE_NEXT_ABI */
pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(
rxdp[j].wb.lower.lo_dword.data);
/* reuse status field from scan list */
pkt_flags |= rx_desc_status_to_pkt_flags(s[j]);
pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
mb->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
mb->hash.rss = rxdp[j].wb.lower.hi_dword.rss;
@@ -1211,7 +1338,11 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
union ixgbe_adv_rx_desc rxd;
uint64_t dma_addr;
uint32_t staterr;
+#ifdef RTE_NEXT_ABI
+ uint32_t pkt_info;
+#else
uint32_t hlen_type_rss;
+#endif
uint16_t pkt_len;
uint16_t rx_id;
uint16_t nb_rx;
@@ -1329,6 +1460,19 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
rxm->data_len = pkt_len;
rxm->port = rxq->port_id;
+#ifdef RTE_NEXT_ABI
+ pkt_info = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.hs_rss.
+ pkt_info);
+ /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
+ rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
+
+ pkt_flags = rx_desc_status_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags |
+ ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info);
+ rxm->ol_flags = pkt_flags;
+ rxm->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info);
+#else /* RTE_NEXT_ABI */
hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data);
/* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
@@ -1337,6 +1481,7 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
rxm->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
rxm->hash.rss = rxd.wb.lower.hi_dword.rss;
@@ -1410,6 +1555,23 @@ ixgbe_fill_cluster_head_buf(
uint8_t port_id,
uint32_t staterr)
{
+#ifdef RTE_NEXT_ABI
+ uint16_t pkt_info;
+ uint64_t pkt_flags;
+
+ head->port = port_id;
+
+ /* The vlan_tci field is only valid when PKT_RX_VLAN_PKT is
+ * set in the pkt_flags field.
+ */
+ head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan);
+ pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.hs_rss.pkt_info);
+ pkt_flags = rx_desc_status_to_pkt_flags(staterr);
+ pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info);
+ head->ol_flags = pkt_flags;
+ head->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info);
+#else /* RTE_NEXT_ABI */
uint32_t hlen_type_rss;
uint64_t pkt_flags;
@@ -1425,6 +1587,7 @@ ixgbe_fill_cluster_head_buf(
pkt_flags |= rx_desc_status_to_pkt_flags(staterr);
pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
head->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
head->hash.rss = rte_le_to_cpu_32(desc->wb.lower.hi_dword.rss);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 04/18] e1000: replace bit mask based packet type with unified packet type
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
` (2 preceding siblings ...)
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 05/18] ixgbe: " Helin Zhang
` (15 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/e1000/igb_rxtx.c | 102 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index 43d6703..d1c2ef8 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -590,6 +590,99 @@ eth_igb_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
* RX functions
*
**********************************************************************/
+#ifdef RTE_NEXT_ABI
+#define IGB_PACKET_TYPE_IPV4 0X01
+#define IGB_PACKET_TYPE_IPV4_TCP 0X11
+#define IGB_PACKET_TYPE_IPV4_UDP 0X21
+#define IGB_PACKET_TYPE_IPV4_SCTP 0X41
+#define IGB_PACKET_TYPE_IPV4_EXT 0X03
+#define IGB_PACKET_TYPE_IPV4_EXT_SCTP 0X43
+#define IGB_PACKET_TYPE_IPV6 0X04
+#define IGB_PACKET_TYPE_IPV6_TCP 0X14
+#define IGB_PACKET_TYPE_IPV6_UDP 0X24
+#define IGB_PACKET_TYPE_IPV6_EXT 0X0C
+#define IGB_PACKET_TYPE_IPV6_EXT_TCP 0X1C
+#define IGB_PACKET_TYPE_IPV6_EXT_UDP 0X2C
+#define IGB_PACKET_TYPE_IPV4_IPV6 0X05
+#define IGB_PACKET_TYPE_IPV4_IPV6_TCP 0X15
+#define IGB_PACKET_TYPE_IPV4_IPV6_UDP 0X25
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT 0X0D
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D
+#define IGB_PACKET_TYPE_MAX 0X80
+#define IGB_PACKET_TYPE_MASK 0X7F
+#define IGB_PACKET_TYPE_SHIFT 0X04
+static inline uint32_t
+igb_rxd_pkt_info_to_pkt_type(uint16_t pkt_info)
+{
+ static const uint32_t
+ ptype_table[IGB_PACKET_TYPE_MAX] __rte_cache_aligned = {
+ [IGB_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4,
+ [IGB_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [IGB_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6,
+ [IGB_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IGB_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ [IGB_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP,
+ [IGB_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP,
+ [IGB_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP,
+ [IGB_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP,
+ };
+ if (unlikely(pkt_info & E1000_RXDADV_PKTTYPE_ETQF))
+ return RTE_PTYPE_UNKNOWN;
+
+ pkt_info = (pkt_info >> IGB_PACKET_TYPE_SHIFT) & IGB_PACKET_TYPE_MASK;
+
+ return ptype_table[pkt_info];
+}
+
+static inline uint64_t
+rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
+{
+ uint64_t pkt_flags = ((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH;
+
+#if defined(RTE_LIBRTE_IEEE1588)
+ static uint32_t ip_pkt_etqf_map[8] = {
+ 0, 0, 0, PKT_RX_IEEE1588_PTP,
+ 0, 0, 0, 0,
+ };
+
+ pkt_flags |= ip_pkt_etqf_map[(hl_tp_rs >> 4) & 0x07];
+#endif
+
+ return pkt_flags;
+}
+#else /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
{
@@ -617,6 +710,7 @@ rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
#endif
return pkt_flags | (((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH);
}
+#endif /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_status_to_pkt_flags(uint32_t rx_status)
@@ -790,6 +884,10 @@ eth_igb_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
rxm->ol_flags = pkt_flags;
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.lower.
+ lo_dword.hs_rss.pkt_info);
+#endif
/*
* Store the mbuf address into the next entry of the array
@@ -1024,6 +1122,10 @@ eth_igb_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
first_seg->ol_flags = pkt_flags;
+#ifdef RTE_NEXT_ABI
+ first_seg->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.
+ lower.lo_dword.hs_rss.pkt_info);
+#endif
/* Prefetch data of first segment, if configured to do so. */
rte_packet_prefetch((char *)first_seg->buf_addr +
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 02/18] ixgbe: support unified packet type in vectorized PMD Helin Zhang
@ 2015-06-23 1:50 3% ` Helin Zhang
2015-06-30 8:43 0% ` Olivier MATZ
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 04/18] e1000: replace bit mask based packet type with unified packet type Helin Zhang
` (16 subsequent siblings)
19 siblings, 1 reply; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
As there are only 6 bit flags in ol_flags for indicating packet
types, which is not enough to describe all the possible packet
types hardware can recognize. For example, i40e hardware can
recognize more than 150 packet types. Unified packet type is
composed of L2 type, L3 type, L4 type, tunnel type, inner L2 type,
inner L3 type and inner L4 type fields, and can be stored in
'struct rte_mbuf' of 32 bits field 'packet_type'.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_mbuf/rte_mbuf.h | 487 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 487 insertions(+)
v3 changes:
* Put the definitions of unified packet type into a single patch.
v4 changes:
* Added detailed description of each packet types.
v5 changes:
* Re-worded the commit logs.
* Added more detailed description for all packet types, together with examples.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 0315561..0ee0c55 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -201,6 +201,493 @@ extern "C" {
/* Use final bit of flags to indicate a control mbuf */
#define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control data */
+#ifdef RTE_NEXT_ABI
+/*
+ * 32 bits are divided into several fields to mark packet types. Note that
+ * each field is indexical.
+ * - Bit 3:0 is for L2 types.
+ * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
+ * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
+ * - Bit 15:12 is for tunnel types.
+ * - Bit 19:16 is for inner L2 types.
+ * - Bit 23:20 is for inner L3 types.
+ * - Bit 27:24 is for inner L4 types.
+ * - Bit 31:28 is reserved.
+ *
+ * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT,
+ * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP
+ * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
+ *
+ * Note that L3 types values are selected for checking IPV4/IPV6 header from
+ * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and
+ * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
+ *
+ * Note that the packet types of the same packet recognized by different
+ * hardware may be different, as different hardware may have different
+ * capability of packet type recognition.
+ *
+ * examples:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=0x29
+ * | 'version'=6, 'next header'=0x3A
+ * | 'ICMPv6 header'>
+ * will be recognized on i40e hardware as packet type combination of,
+ * RTE_PTYPE_L2_MAC |
+ * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ * RTE_PTYPE_TUNNEL_IP |
+ * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_INNER_L4_ICMP.
+ *
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x2F
+ * | 'GRE header'
+ * | 'version'=6, 'next header'=0x11
+ * | 'UDP header'>
+ * will be recognized on i40e hardware as packet type combination of,
+ * RTE_PTYPE_L2_MAC |
+ * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_TUNNEL_GRENAT |
+ * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_INNER_L4_UDP.
+ */
+#define RTE_PTYPE_UNKNOWN 0x00000000
+/**
+ * MAC (Media Access Control) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=[0x0800|0x86DD|others]>
+ */
+#define RTE_PTYPE_L2_MAC 0x00000001
+/**
+ * MAC (Media Access Control) packet type for time sync.
+ *
+ * Packet format:
+ * <'ether type'=0x88F7>
+ */
+#define RTE_PTYPE_L2_MAC_TIMESYNC 0x00000002
+/**
+ * ARP (Address Resolution Protocol) packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0806>
+ */
+#define RTE_PTYPE_L2_ARP 0x00000003
+/**
+ * LLDP (Link Layer Discovery Protocol) packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x88CC>
+ */
+#define RTE_PTYPE_L2_LLDP 0x00000004
+/**
+ * Mask of layer 2 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L2_MASK 0x0000000f
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and does not contain any
+ * header option.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=5>
+ */
+#define RTE_PTYPE_L3_IPV4 0x00000010
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and contains header
+ * options.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[6-15], 'options'>
+ */
+#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and does not contain any
+ * extension header.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x3B>
+ */
+#define RTE_PTYPE_L3_IPV6 0x00000040
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and may or maynot contain
+ * header options.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[5-15], <'options'>>
+ */
+#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and contains extension
+ * headers.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * 'extension headers'>
+ */
+#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and may or maynot contain
+ * extension headers.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * <'extension headers'>>
+ */
+#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
+/**
+ * Mask of layer 3 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L3_MASK 0x000000f0
+/**
+ * TCP (Transmission Control Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=6, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=6>
+ */
+#define RTE_PTYPE_L4_TCP 0x00000100
+/**
+ * UDP (User Datagram Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17>
+ */
+#define RTE_PTYPE_L4_UDP 0x00000200
+/**
+ * Fragmented IP (Internet Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * It refers to those packets of any IP types, which can be recognized as
+ * fragmented. A fragmented packet cannot be recognized as any other L4 types
+ * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP,
+ * RTE_PTYPE_L4_NONFRAG).
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'MF'=1>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=44>
+ */
+#define RTE_PTYPE_L4_FRAG 0x00000300
+/**
+ * SCTP (Stream Control Transmission Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=132, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=132>
+ */
+#define RTE_PTYPE_L4_SCTP 0x00000400
+/**
+ * ICMP (Internet Control Message Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=1, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=1>
+ */
+#define RTE_PTYPE_L4_ICMP 0x00000500
+/**
+ * Non-fragmented IP (Internet Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * It refers to those packets of any IP types, while cannot be recognized as
+ * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
+ * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'!=[6|17|44|132|1]>
+ */
+#define RTE_PTYPE_L4_NONFRAG 0x00000600
+/**
+ * Mask of layer 4 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L4_MASK 0x00000f00
+/**
+ * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=[4|41]>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[4|41]>
+ */
+#define RTE_PTYPE_TUNNEL_IP 0x00001000
+/**
+ * GRE (Generic Routing Encapsulation) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=47>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=47>
+ */
+#define RTE_PTYPE_TUNNEL_GRE 0x00002000
+/**
+ * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17
+ * | 'destination port'=4798>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17
+ * | 'destination port'=4798>
+ */
+#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
+/**
+ * NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling
+ * packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=47
+ * | 'protocol type'=0x6558>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=47
+ * | 'protocol type'=0x6558'>
+ */
+#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
+/**
+ * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17
+ * | 'destination port'=6081>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17
+ * | 'destination port'=6081>
+ */
+#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
+/**
+ * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area
+ * Network) or GRE (Generic Routing Encapsulation) could be recognized as this
+ * packet type, if they can not be recognized independently as of hardware
+ * capability.
+ */
+#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
+/**
+ * Mask of tunneling packet types.
+ */
+#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
+/**
+ * MAC (Media Access Control) packet type.
+ * It is used for inner packet type only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=[0x800|0x86DD]>
+ */
+#define RTE_PTYPE_INNER_L2_MAC 0x00010000
+/**
+ * MAC (Media Access Control) packet type with VLAN (Virtual Local Area
+ * Network) tag.
+ *
+ * Packet format (inner only):
+ * <'ether type'=[0x800|0x86DD], vlan=[1-4095]>
+ */
+#define RTE_PTYPE_INNER_L2_MAC_VLAN 0x00020000
+/**
+ * Mask of inner layer 2 packet types.
+ */
+#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and does not contain any header option.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=5>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and contains header options.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[6-15], 'options'>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and does not contain any extension header.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x3B>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and may or maynot contain header options.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[5-15], <'options'>>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and contains extension headers.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * 'extension headers'>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and may or maynot contain extension
+ * headers.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * <'extension headers'>>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
+/**
+ * Mask of inner layer 3 packet types.
+ */
+#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
+/**
+ * TCP (Transmission Control Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=6, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=6>
+ */
+#define RTE_PTYPE_INNER_L4_TCP 0x01000000
+/**
+ * UDP (User Datagram Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17>
+ */
+#define RTE_PTYPE_INNER_L4_UDP 0x02000000
+/**
+ * Fragmented IP (Internet Protocol) packet type.
+ * It is used for inner packet only, and may or maynot have layer 4 packet.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'MF'=1>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=44>
+ */
+#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
+/**
+ * SCTP (Stream Control Transmission Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=132, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=132>
+ */
+#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
+/**
+ * ICMP (Internet Control Message Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=1, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=1>
+ */
+#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
+/**
+ * Non-fragmented IP (Internet Protocol) packet type.
+ * It is used for inner packet only, and may or maynot have other unknown layer
+ * 4 packet types.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'!=[6|17|44|132|1]>
+ */
+#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
+/**
+ * Mask of inner layer 4 packet types.
+ */
+#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
+
+/**
+ * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
+ * one, bit 4 is selected to be used for IPv4 only. Then checking bit 4 can
+ * determin if it is an IPV4 packet.
+ */
+#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
+
+/**
+ * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
+ * one, bit 6 is selected to be used for IPv4 only. Then checking bit 6 can
+ * determin if it is an IPV4 packet.
+ */
+#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
+
+/* Check if it is a tunneling packet */
+#define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
+#endif /* RTE_NEXT_ABI */
+
/**
* Get the name of a RX offload flag
*
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 02/18] ixgbe: support unified packet type in vectorized PMD
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
@ 2015-06-23 1:50 3% ` Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types Helin Zhang
` (17 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
To unify the packet type, bit masks of packet type for ol_flags are
replaced. In addition, more packet types (UDP, TCP and SCTP) are
supported in vectorized ixgbe PMD.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Note that around 2% performance drop (64B) was observed of doing 4
ports (1 port per 82599 card) IO forwarding on the same SNB core.
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
config/common_linuxapp | 2 +-
drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 +++++++++++++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 3 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v3 changes:
* Put vector ixgbe changes right after mbuf changes.
* Enabled vector ixgbe PMD by default together with changes for updated
vector PMD.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 617d4a1..5deb55a 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -167,7 +167,7 @@ CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
CONFIG_RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC=y
-CONFIG_RTE_IXGBE_INC_VECTOR=n
+CONFIG_RTE_IXGBE_INC_VECTOR=y
CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y
#
diff --git a/drivers/net/ixgbe/ixgbe_rxtx_vec.c b/drivers/net/ixgbe/ixgbe_rxtx_vec.c
index abd10f6..ccea7cd 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx_vec.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx_vec.c
@@ -134,6 +134,12 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
*/
#ifdef RTE_IXGBE_RX_OLFLAGS_ENABLE
+#ifdef RTE_NEXT_ABI
+#define OLFLAGS_MASK_V (((uint64_t)PKT_RX_VLAN_PKT << 48) | \
+ ((uint64_t)PKT_RX_VLAN_PKT << 32) | \
+ ((uint64_t)PKT_RX_VLAN_PKT << 16) | \
+ ((uint64_t)PKT_RX_VLAN_PKT))
+#else
#define OLFLAGS_MASK ((uint16_t)(PKT_RX_VLAN_PKT | PKT_RX_IPV4_HDR |\
PKT_RX_IPV4_HDR_EXT | PKT_RX_IPV6_HDR |\
PKT_RX_IPV6_HDR_EXT))
@@ -142,11 +148,26 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
((uint64_t)OLFLAGS_MASK << 16) | \
((uint64_t)OLFLAGS_MASK))
#define PTYPE_SHIFT (1)
+#endif /* RTE_NEXT_ABI */
+
#define VTAG_SHIFT (3)
static inline void
desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
{
+#ifdef RTE_NEXT_ABI
+ __m128i vtag0, vtag1;
+ union {
+ uint16_t e[4];
+ uint64_t dword;
+ } vol;
+
+ vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]);
+ vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]);
+ vtag1 = _mm_unpacklo_epi32(vtag0, vtag1);
+ vtag1 = _mm_srli_epi16(vtag1, VTAG_SHIFT);
+ vol.dword = _mm_cvtsi128_si64(vtag1) & OLFLAGS_MASK_V;
+#else
__m128i ptype0, ptype1, vtag0, vtag1;
union {
uint16_t e[4];
@@ -166,6 +187,7 @@ desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
ptype1 = _mm_or_si128(ptype1, vtag1);
vol.dword = _mm_cvtsi128_si64(ptype1) & OLFLAGS_MASK_V;
+#endif /* RTE_NEXT_ABI */
rx_pkts[0]->ol_flags = vol.e[0];
rx_pkts[1]->ol_flags = vol.e[1];
@@ -196,6 +218,18 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
int pos;
uint64_t var;
__m128i shuf_msk;
+#ifdef RTE_NEXT_ABI
+ __m128i crc_adjust = _mm_set_epi16(
+ 0, 0, 0, /* ignore non-length fields */
+ -rxq->crc_len, /* sub crc on data_len */
+ 0, /* ignore high-16bits of pkt_len */
+ -rxq->crc_len, /* sub crc on pkt_len */
+ 0, 0 /* ignore pkt_type field */
+ );
+ __m128i dd_check, eop_check;
+ __m128i desc_mask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFF07F0);
+#else
__m128i crc_adjust = _mm_set_epi16(
0, 0, 0, 0, /* ignore non-length fields */
0, /* ignore high-16bits of pkt_len */
@@ -204,6 +238,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
0 /* ignore pkt_type field */
);
__m128i dd_check, eop_check;
+#endif /* RTE_NEXT_ABI */
if (unlikely(nb_pkts < RTE_IXGBE_VPMD_RX_BURST))
return 0;
@@ -232,6 +267,18 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
eop_check = _mm_set_epi64x(0x0000000200000002LL, 0x0000000200000002LL);
/* mask to shuffle from desc. to mbuf */
+#ifdef RTE_NEXT_ABI
+ shuf_msk = _mm_set_epi8(
+ 7, 6, 5, 4, /* octet 4~7, 32bits rss */
+ 15, 14, /* octet 14~15, low 16 bits vlan_macip */
+ 13, 12, /* octet 12~13, 16 bits data_len */
+ 0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */
+ 13, 12, /* octet 12~13, low 16 bits pkt_len */
+ 0xFF, 0xFF, /* skip high 16 bits pkt_type */
+ 1, /* octet 1, 8 bits pkt_type field */
+ 0 /* octet 0, 4 bits offset 4 pkt_type field */
+ );
+#else
shuf_msk = _mm_set_epi8(
7, 6, 5, 4, /* octet 4~7, 32bits rss */
0xFF, 0xFF, /* skip high 16 bits vlan_macip, zero out */
@@ -241,18 +288,28 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
13, 12, /* octet 12~13, 16 bits data_len */
0xFF, 0xFF /* skip pkt_type field */
);
+#endif /* RTE_NEXT_ABI */
/* Cache is empty -> need to scan the buffer rings, but first move
* the next 'n' mbufs into the cache */
sw_ring = &rxq->sw_ring[rxq->rx_tail];
- /*
- * A. load 4 packet in one loop
+#ifdef RTE_NEXT_ABI
+ /* A. load 4 packet in one loop
+ * [A*. mask out 4 unused dirty field in desc]
* B. copy 4 mbuf point from swring to rx_pkts
* C. calc the number of DD bits among the 4 packets
* [C*. extract the end-of-packet bit, if requested]
* D. fill info. from desc to mbuf
*/
+#else
+ /* A. load 4 packet in one loop
+ * B. copy 4 mbuf point from swring to rx_pkts
+ * C. calc the number of DD bits among the 4 packets
+ * [C*. extract the end-of-packet bit, if requested]
+ * D. fill info. from desc to mbuf
+ */
+#endif /* RTE_NEXT_ABI */
for (pos = 0, nb_pkts_recd = 0; pos < RTE_IXGBE_VPMD_RX_BURST;
pos += RTE_IXGBE_DESCS_PER_LOOP,
rxdp += RTE_IXGBE_DESCS_PER_LOOP) {
@@ -289,6 +346,16 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
/* B.2 copy 2 mbuf point into rx_pkts */
_mm_storeu_si128((__m128i *)&rx_pkts[pos+2], mbp2);
+#ifdef RTE_NEXT_ABI
+ /* A* mask out 0~3 bits RSS type */
+ descs[3] = _mm_and_si128(descs[3], desc_mask);
+ descs[2] = _mm_and_si128(descs[2], desc_mask);
+
+ /* A* mask out 0~3 bits RSS type */
+ descs[1] = _mm_and_si128(descs[1], desc_mask);
+ descs[0] = _mm_and_si128(descs[0], desc_mask);
+#endif /* RTE_NEXT_ABI */
+
/* avoid compiler reorder optimization */
rte_compiler_barrier();
@@ -301,7 +368,11 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
/* C.1 4=>2 filter staterr info only */
sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]);
+#ifdef RTE_NEXT_ABI
+ /* set ol_flags with vlan packet type */
+#else
/* set ol_flags with packet type and vlan tag */
+#endif /* RTE_NEXT_ABI */
desc_to_olflags_v(descs, &rx_pkts[pos]);
/* D.2 pkt 3,4 set in_port/nb_seg and remove crc */
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v8 01/18] mbuf: redefine packet_type in rte_mbuf
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 02/18] ixgbe: support unified packet type in vectorized PMD Helin Zhang
` (18 subsequent siblings)
19 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
In order to unify the packet type, the field of 'packet_type' in
'struct rte_mbuf' needs to be extended from 16 to 32 bits.
Accordingly, some fields in 'struct rte_mbuf' are re-organized to
support this change for Vector PMD. As 'struct rte_kni_mbuf' for
KNI should be right mapped to 'struct rte_mbuf', it should be
modified accordingly. In addition, Vector PMD of ixgbe is disabled
by default, as 'struct rte_mbuf' changed.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
config/common_linuxapp | 2 +-
.../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 +++++
lib/librte_mbuf/rte_mbuf.h | 26 ++++++++++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
v2 changes:
* Enlarged the packet_type field from 16 bits to 32 bits.
* Redefined the packet type sub-fields.
* Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
v3 changes:
* Put the mbuf layout changes into a single patch.
* Disabled vector ixgbe PMD by default, as mbuf layout changed.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
* Integrated with changes of QinQ stripping/insertion.
v8 changes:
* Moved the field of 'vlan_tci_outer' in 'struct rte_mbuf' to the end
of the 1st cache line, to avoid breaking any vectorized PMD storing.
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 5deb55a..617d4a1 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -167,7 +167,7 @@ CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
CONFIG_RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC=y
-CONFIG_RTE_IXGBE_INC_VECTOR=y
+CONFIG_RTE_IXGBE_INC_VECTOR=n
CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y
#
diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
index 1e55c2d..e9f38bd 100644
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
@@ -117,9 +117,15 @@ struct rte_kni_mbuf {
uint16_t data_off; /**< Start address of data in segment buffer. */
char pad1[4];
uint64_t ol_flags; /**< Offload features. */
+#ifdef RTE_NEXT_ABI
+ char pad2[4];
+ uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
+ uint16_t data_len; /**< Amount of data in segment buffer. */
+#else
char pad2[2];
uint16_t data_len; /**< Amount of data in segment buffer. */
uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
+#endif
/* fields on second cache line */
char pad3[8] __attribute__((__aligned__(RTE_CACHE_LINE_SIZE)));
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index a0f3d3b..0315561 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -275,6 +275,28 @@ struct rte_mbuf {
/* remaining bytes are set on RX when pulling packet from descriptor */
MARKER rx_descriptor_fields1;
+#ifdef RTE_NEXT_ABI
+ /*
+ * The packet type, which is the combination of outer/inner L2, L3, L4
+ * and tunnel types.
+ */
+ union {
+ uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */
+ struct {
+ uint32_t l2_type:4; /**< (Outer) L2 type. */
+ uint32_t l3_type:4; /**< (Outer) L3 type. */
+ uint32_t l4_type:4; /**< (Outer) L4 type. */
+ uint32_t tun_type:4; /**< Tunnel type. */
+ uint32_t inner_l2_type:4; /**< Inner L2 type. */
+ uint32_t inner_l3_type:4; /**< Inner L3 type. */
+ uint32_t inner_l4_type:4; /**< Inner L4 type. */
+ };
+ };
+
+ uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
+ uint16_t data_len; /**< Amount of data in segment buffer. */
+ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
+#else /* RTE_NEXT_ABI */
/**
* The packet type, which is used to indicate ordinary packet and also
* tunneled packet format, i.e. each number is represented a type of
@@ -286,6 +308,7 @@ struct rte_mbuf {
uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */
+#endif /* RTE_NEXT_ABI */
union {
uint32_t rss; /**< RSS hash result if RSS enabled */
struct {
@@ -306,6 +329,9 @@ struct rte_mbuf {
} hash; /**< hash information */
uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */
+#ifdef RTE_NEXT_ABI
+ uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */
+#endif /* RTE_NEXT_ABI */
/* second cache line - fields only used in slow path or on TX */
MARKER cacheline1 __rte_cache_aligned;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v8 00/18] unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (17 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 18/18] mbuf: remove old packet type bit masks Helin Zhang
@ 2015-06-23 1:50 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
` (19 more replies)
18 siblings, 20 replies; 200+ results
From: Helin Zhang @ 2015-06-23 1:50 UTC (permalink / raw)
To: dev
Currently only 6 bits which are stored in ol_flags are used to indicate the
packet types. This is not enough, as some NIC hardware can recognize quite
a lot of packet types, e.g i40e hardware can recognize more than 150 packet
types. Hiding those packet types hides hardware offload capabilities which
could be quite useful for improving performance and for end users.
So an unified packet types are needed to support all possible PMDs. A 16
bits packet_type in mbuf structure can be changed to 32 bits and used for
this purpose. In addition, all packet types stored in ol_flag field should
be deleted at all, and 6 bits of ol_flags can be save as the benifit.
Initially, 32 bits of packet_type can be divided into several sub fields to
indicate different packet type information of a packet. The initial design
is to divide those bits into fields for L2 types, L3 types, L4 types, tunnel
types, inner L2 types, inner L3 types and inner L4 types. All PMDs should
translate the offloaded packet types into these 7 fields of information, for
user applications.
To avoid breaking ABI compatibility, currently all the code changes for
unified packet type are disabled at compile time by default. Users can enable
it manually by defining the macro of RTE_NEXT_ABI. The code changes will be
valid by default in a future release, and the old version will be deleted
accordingly, after the ABI change process is done.
Note that this patch set should be integrated after another patch set for
'[PATCH v3 0/7] support i40e QinQ stripping and insertion', to clearly solve
the conflict during integration. As both patch sets modified 'struct rte_mbuf',
and the final layout of the 'struct rte_mbuf' is key to vectorized ixgbe PMD.
v2 changes:
* Enlarged the packet_type field from 16 bits to 32 bits.
* Redefined the packet type sub-fields.
* Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
* Used redefined packet types and enlarged packet_type field for all PMDs
and corresponding applications.
* Removed changes in bond and its relevant application, as there is no need
at all according to the recent bond changes.
v3 changes:
* Put the mbuf layout changes into a single patch.
* Put vector ixgbe changes right after mbuf changes.
* Disabled vector ixgbe PMD by default, as mbuf layout changed, and then
re-enabled it after vector ixgbe PMD updated.
* Put the definitions of unified packet type into a single patch.
* Minor bug fixes and enhancements in l3fwd example.
v4 changes:
* Added detailed description of each packet types.
* Supported unified packet type of fm10k.
* Added printing logs of packet types of each received packet for rxonly
mode in testpmd.
* Removed several useless code lines which block packet type unification from
app/test/packet_burst_generator.c.
v5 changes:
* Added more detailed description for each packet types, together with examples.
* Rolled back the macro definitions of RX packet flags, for ABI compitability.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
* Integrated with patch set for '[PATCH v3 0/7] support i40e QinQ stripping
and insertion', to clearly solve the conflicts during merging.
v8 changes:
* Moved the field of 'vlan_tci_outer' in 'struct rte_mbuf' to the end of the 1st
cache line, to avoid breaking any vectorized PMD storing, as fields of
'packet_type, pkt_len, data_len, vlan_tci, rss' should be in an contiguous 128
bits.
Helin Zhang (18):
mbuf: redefine packet_type in rte_mbuf
ixgbe: support unified packet type in vectorized PMD
mbuf: add definitions of unified packet types
e1000: replace bit mask based packet type with unified packet type
ixgbe: replace bit mask based packet type with unified packet type
i40e: replace bit mask based packet type with unified packet type
enic: replace bit mask based packet type with unified packet type
vmxnet3: replace bit mask based packet type with unified packet type
fm10k: replace bit mask based packet type with unified packet type
app/test-pipeline: replace bit mask based packet type with unified
packet type
app/testpmd: replace bit mask based packet type with unified packet
type
app/test: Remove useless code
examples/ip_fragmentation: replace bit mask based packet type with
unified packet type
examples/ip_reassembly: replace bit mask based packet type with
unified packet type
examples/l3fwd-acl: replace bit mask based packet type with unified
packet type
examples/l3fwd-power: replace bit mask based packet type with unified
packet type
examples/l3fwd: replace bit mask based packet type with unified packet
type
mbuf: remove old packet type bit masks
app/test-pipeline/pipeline_hash.c | 13 +
app/test-pmd/csumonly.c | 14 +
app/test-pmd/rxonly.c | 183 +++++++
app/test/packet_burst_generator.c | 6 +-
drivers/net/e1000/igb_rxtx.c | 102 ++++
drivers/net/enic/enic_main.c | 26 +
drivers/net/fm10k/fm10k_rxtx.c | 27 ++
drivers/net/i40e/i40e_rxtx.c | 528 +++++++++++++++++++++
drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++
drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 ++-
drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 +
examples/ip_fragmentation/main.c | 9 +
examples/ip_reassembly/main.c | 9 +
examples/l3fwd-acl/main.c | 29 +-
examples/l3fwd-power/main.c | 8 +
examples/l3fwd/main.c | 123 ++++-
.../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 +
lib/librte_mbuf/rte_mbuf.c | 4 +
lib/librte_mbuf/rte_mbuf.h | 517 ++++++++++++++++++++
19 files changed, 1837 insertions(+), 13 deletions(-)
--
1.9.3
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v2 08/12] mempool: allow config override on element alignment
@ 2015-06-23 0:31 3% ` Ananyev, Konstantin
2015-06-23 20:43 4% ` Cyril Chemparathy
0 siblings, 1 reply; 200+ results
From: Ananyev, Konstantin @ 2015-06-23 0:31 UTC (permalink / raw)
To: Cyril Chemparathy, dev
Hi Cyril,
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Cyril Chemparathy
> Sent: Monday, June 22, 2015 7:59 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2 08/12] mempool: allow config override on element alignment
>
> On TILE-Gx and TILE-Mx platforms, the buffers fed into the hardware
> buffer manager require a 128-byte alignment. With this change, we
> allow configuration based override of the element alignment, and
> default to RTE_CACHE_LINE_SIZE if left unspecified.
>
> Change-Id: I9cd789d92b0bc9c8f44a633de59bb04d45d927a7
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
> lib/librte_mempool/rte_mempool.c | 16 +++++++++-------
> lib/librte_mempool/rte_mempool.h | 6 ++++++
> 2 files changed, 15 insertions(+), 7 deletions(-)
>
> diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
> index 002d3a8..7656b0f 100644
> --- a/lib/librte_mempool/rte_mempool.c
> +++ b/lib/librte_mempool/rte_mempool.c
> @@ -120,10 +120,10 @@ static unsigned optimize_object_size(unsigned obj_size)
> nrank = 1;
>
> /* process new object size */
> - new_obj_size = (obj_size + RTE_CACHE_LINE_MASK) / RTE_CACHE_LINE_SIZE;
> + new_obj_size = (obj_size + RTE_MEMPOOL_ALIGN_MASK) / RTE_MEMPOOL_ALIGN;
> while (get_gcd(new_obj_size, nrank * nchan) != 1)
> new_obj_size++;
> - return new_obj_size * RTE_CACHE_LINE_SIZE;
> + return new_obj_size * RTE_MEMPOOL_ALIGN;
> }
>
> static void
> @@ -267,7 +267,7 @@ rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags,
> #endif
> if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0)
> sz->header_size = RTE_ALIGN_CEIL(sz->header_size,
> - RTE_CACHE_LINE_SIZE);
> + RTE_MEMPOOL_ALIGN);
>
> /* trailer contains the cookie in debug mode */
> sz->trailer_size = 0;
> @@ -281,9 +281,9 @@ rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags,
> if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0) {
> sz->total_size = sz->header_size + sz->elt_size +
> sz->trailer_size;
> - sz->trailer_size += ((RTE_CACHE_LINE_SIZE -
> - (sz->total_size & RTE_CACHE_LINE_MASK)) &
> - RTE_CACHE_LINE_MASK);
> + sz->trailer_size += ((RTE_MEMPOOL_ALIGN -
> + (sz->total_size & RTE_MEMPOOL_ALIGN_MASK)) &
> + RTE_MEMPOOL_ALIGN_MASK);
> }
>
> /*
> @@ -498,7 +498,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
> * cache-aligned
> */
> private_data_size = (private_data_size +
> - RTE_CACHE_LINE_MASK) & (~RTE_CACHE_LINE_MASK);
> + RTE_MEMPOOL_ALIGN_MASK) & (~RTE_MEMPOOL_ALIGN_MASK);
>
> if (! rte_eal_has_hugepages()) {
> /*
> @@ -525,6 +525,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
> * enough to hold mempool header and metadata plus mempool objects.
> */
> mempool_size = MEMPOOL_HEADER_SIZE(mp, pg_num) + private_data_size;
> + mempool_size = RTE_ALIGN_CEIL(mempool_size, RTE_MEMPOOL_ALIGN);
> if (vaddr == NULL)
> mempool_size += (size_t)objsz.total_size * n;
>
> @@ -580,6 +581,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
> /* calculate address of the first element for continuous mempool. */
> obj = (char *)mp + MEMPOOL_HEADER_SIZE(mp, pg_num) +
> private_data_size;
> + obj = RTE_PTR_ALIGN_CEIL(obj, RTE_MEMPOOL_ALIGN);
>
> /* populate address translation fields. */
> mp->pg_num = pg_num;
> diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
> index 380d60b..9321b86 100644
> --- a/lib/librte_mempool/rte_mempool.h
> +++ b/lib/librte_mempool/rte_mempool.h
> @@ -142,6 +142,12 @@ struct rte_mempool_objsz {
> /** Mempool over one chunk of physically continuous memory */
> #define MEMPOOL_PG_NUM_DEFAULT 1
>
> +#ifndef RTE_MEMPOOL_ALIGN
> +#define RTE_MEMPOOL_ALIGN RTE_CACHE_LINE_SIZE
> +#endif
> +
> +#define RTE_MEMPOOL_ALIGN_MASK (RTE_MEMPOOL_ALIGN - 1)
I am probably a bit late with my comments, but why not make it a runtime decision then?
I know we can't add a new parameter to mempool_xmem_create() without ABI breakage,
but we can make some global variable for now, that could be setup at init time or something similar.
> +
> /**
> * Mempool object header structure
> *
> --
> 2.1.2
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH] lib: fix RTE_MBUF_METADATA macros
2015-06-22 20:16 0% ` Thomas Monjalon
2015-06-22 20:23 0% ` Cyril Chemparathy
@ 2015-06-22 20:34 0% ` Cyril Chemparathy
1 sibling, 0 replies; 200+ results
From: Cyril Chemparathy @ 2015-06-22 20:34 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Mon, 22 Jun 2015 22:16:59 +0200
Thomas Monjalon <thomas.monjalon@6wind.com> wrote:
> 2015-06-05 15:31, Dumitrescu, Cristian:
> > > Fix RTE_MBUF_METADATA macros to allow for unaligned accesses to
> > > meta-data fields.
> > > Forcing aligned accesses is not really required, so this is
> > > removing an unneeded constraint.
> > > This issue was met during testing of the new version of the
> > > ip_pipeline application. There is no performance impact.
> > > This change has no ABI impact, as the previous code that uses
> > > aligned accesses continues to run without any issues.
> > >
> > > Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
> >
> > Ack-ed by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
>
> Applied, thanks
>
> Cyril, feel free to fix it if it breaks with Tile arch.
Also, in the code, doesn't the following break when mbuf_priv_size != 0?
> #define RTE_MBUF_METADATA_UINT8_PTR(mbuf, offset) \
> (&((uint8_t *) &(mbuf)[1])[offset])
Thanks
-- Cyril.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH] lib: fix RTE_MBUF_METADATA macros
2015-06-22 20:16 0% ` Thomas Monjalon
@ 2015-06-22 20:23 0% ` Cyril Chemparathy
2015-06-22 20:34 0% ` Cyril Chemparathy
1 sibling, 0 replies; 200+ results
From: Cyril Chemparathy @ 2015-06-22 20:23 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Mon, 22 Jun 2015 22:16:59 +0200
Thomas Monjalon <thomas.monjalon@6wind.com> wrote:
> 2015-06-05 15:31, Dumitrescu, Cristian:
> > > Fix RTE_MBUF_METADATA macros to allow for unaligned accesses to
> > > meta-data fields.
> > > Forcing aligned accesses is not really required, so this is
> > > removing an unneeded constraint.
> > > This issue was met during testing of the new version of the
> > > ip_pipeline application. There is no performance impact.
> > > This change has no ABI impact, as the previous code that uses
> > > aligned accesses continues to run without any issues.
> > >
> > > Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
> >
> > Ack-ed by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
>
> Applied, thanks
>
> Cyril, feel free to fix it if it breaks with Tile arch.
Why define these locally within rte_port.h? Shouldn't these macros
really be in rte_mbuf.h?
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH] lib: fix RTE_MBUF_METADATA macros
@ 2015-06-22 20:16 0% ` Thomas Monjalon
2015-06-22 20:23 0% ` Cyril Chemparathy
2015-06-22 20:34 0% ` Cyril Chemparathy
0 siblings, 2 replies; 200+ results
From: Thomas Monjalon @ 2015-06-22 20:16 UTC (permalink / raw)
To: Mrzyglod, DanielX T; +Cc: dev
2015-06-05 15:31, Dumitrescu, Cristian:
> > Fix RTE_MBUF_METADATA macros to allow for unaligned accesses to
> > meta-data fields.
> > Forcing aligned accesses is not really required, so this is removing an
> > unneeded constraint.
> > This issue was met during testing of the new version of the ip_pipeline
> > application. There is no performance impact.
> > This change has no ABI impact, as the previous code that uses aligned
> > accesses continues to run without any issues.
> >
> > Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
>
> Ack-ed by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Applied, thanks
Cyril, feel free to fix it if it breaks with Tile arch.
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] DPDK v2.0.0 has different rte_eal_pci_probe() behavior
[not found] ` <CAO1kT8_C2QJUrNk-fqOQd=WmOkpvNw5jCvxEhfPdHwyCwBuyKA@mail.gmail.com>
@ 2015-06-22 0:32 4% ` Matthew Hall
0 siblings, 0 replies; 200+ results
From: Matthew Hall @ 2015-06-22 0:32 UTC (permalink / raw)
To: <dev@dpdk.org>
On Jun 21, 2015, at 3:54 PM, Tom Barbette <tom.barbette@ulg.ac.be> wrote:
> Application call to rte_eal_pci_probe() is not needed anymore since DPDK 1.8.
>
> http://dpdk.org/ml/archives/dev/2014-September/005890.html
>
> You were not wrong before, it is just a change in DPDK. I came across the same problem a few days ago.
>
> Tom Barbette
So, we have a good practical example below about ABI compatibility.
The prototype and name of the rte_eal_pci_probe() was kept exactly the same, and it compiled fine with no change, but it fails at runtime because it causes a dual-init of all the PCI devices and hits a resource conflict in the process.
Thus it's important to remember you can break compatibility even if the ABI stays the same, if the APIs themselves don't behave the same over time...
Matthew.
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 17:02 8% ` Thomas Monjalon
@ 2015-06-19 17:57 9% ` Thomas F Herbert
0 siblings, 0 replies; 200+ results
From: Thomas F Herbert @ 2015-06-19 17:57 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On 6/19/15 1:02 PM, Thomas Monjalon wrote:
> 2015-06-19 12:13, Thomas F Herbert:
>>
>> On 6/19/15 9:16 AM, Thomas Monjalon wrote:
>>> 2015-06-19 09:02, Neil Horman:
>>>> On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
>>>>> 2015-06-19 06:26, Neil Horman:
>>>>>> On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
>>>>>>> For the 2.1 release, I think we should agree to make patches that change
>>>>>>> the ABI controllable via a compile-time option. I like Olivier's proposal
>>>>>>> on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
>>>>>>> changes instead of a separate option per patch set (see
>>>>>>> http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
>>>>>>> should rework the affected patch sets to use that approach for 2.1.
>>>>>>
>>>>>> This is a bad idea. Making ABI dependent on compile time options isn't a
>>>>>> maintainable solution. It breaks the notion of how LIBABIVER is supposed to
>>>>>> work (that is to say you make it impossible to really tell what ABI version you
>>>>>> are building).
>>>>>
>>>>> The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
>>>>> So one ABI version number refers always to the same ABI.
>>>>>
>>>>>> If you have two compile time options that modify the ABI, you
>>>>>> have to burn through 4 possible LIBABIVER version values to accomodate all
>>>>>> possible combinations, and then you need to remember that when you make them
>>>>>> statically applicable.
>>>>>
>>>>> The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
>>>>>
>>>>> Your intent when introducing ABI policy was to allow smooth porting of
>>>>> applications from a DPDK version to another. Right?
>>>>> The adopted solution was to provide backward compatibility during 1 release.
>>>>> But there are cases where it's not possible. So the policy was to notice
>>>>> the future change and wait one release cycle to break the ABI (failing
>>>>> compatibility goals).
>>>>> The compile-time option may provide an alternative DPDK packaging when the
>>>>> ABI backward compatibility cannot be provided (case of mbuf changes).
>>>>> In such case, it's still possible to upgrade DPDK by providing 2 versions of
>>>>> DPDK libs. So the existing apps continue to link with the previous ABI and
>>>>> have the possibility of migrating to the new one.
>>>>> Another advantage of this approach is that we don't have to wait 1 release
>>>>> to integrate the changes.
>>>>> The last advantage is to benefit early of these changes with static libraries.
>>>>
>>>> Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
>>>> Implementing an ABI preview option like this implies the notion that, after a
>>>> release, you have to remove all the ifdefs that you inserted to create the new
>>>> ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
>>>> large, and is predicated on the centralization of work effort (that is to say
>>>> you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
>>>> from the build' patch every release.
>>>
>>> It won't be so huge if we reserve the NEXT_ABI solution to changes which cannot
>>> have easy backward compatibility with the compat macros you introduced.
>>> I feel I can do the job of removing the ifdefs NEXT_ABI after each release.
>>> At the same time, the deprecated API, using the compat macros, will be removed.
>>>
>>>> What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
>>>> the sort that Thomas Herbert proposed a few weeks ago).
>>>
>>> This tree was created after Thomas' request:
>>> http://dpdk.org/browse/next/dpdk-next/
>>
>> Thomas, I am sorry if I went quiet for awhile but I was on personal
>> travel with inconsistent access so I almost missed most of this
>> discussion about ABI changes.
>>
>> My understanding of the purpose of the dpdk-next tree is to validate
>> patches by applying and compiling against a "pull" from the main dpdk
>> tree. I think a good way to handle ABI change while effectively using
>> the dpdk-next might be to do as follows:
>>
>> Create a specific branch for the new ABI such as 2.X in the main dpdk
>> tree. Once that 2.X branch is created, dpdk-next would mirror the 2.X
>> branch along with master.
>>
>> Since, dpdk-next would also have the 2.X branch that is in the main dpdk
>> tree, submitted patches could be applied to either the main branch or
>> the new-ABI 2.X branch. Providing that patch submitters make it clear
>> whether a submitted patch is for the new ABI or the old ABI, dpdk-next
>> could continue to validate the patches for either the main branch or the
>> new ABI 2.X branch.
>
> What is the benefit of a new-ABI branch in the -next tree?
I don't think that there is any specific benefit to an new-ABI branch in
the dpdk-next tree. I was responding to the suggestion above and perhaps
I missread it. It sounded like what was being proposed was to use the
dpdk-next tree specifically for pre-integration of new-ABI. I don't
think this is of any benefit either.
However if it should be decided to integrate new-ABI patches in a branch
of dpdk rather then in a separate new-ABI tree, then net-next can
"mirror" that branch along with the master branch so patches can be
smoke tested whether they are submitted to the master or to the new-ABI
branch.
>
> The goal of this discussion is to find a consensus on ABI policy to
> smoothly integrate new features without forcing users of shared libraries
> to re-build their application when upgrading DPDK, and let them do the
> transition before the next upgrade.
I understand this and I think it is a good suggestion to have a
mechanism to ease the transition.
>
^ permalink raw reply [relevance 9%]
* [dpdk-dev] [PATCH v3 8/9] doc: announce ABI change of librte_malloc
2015-06-19 17:21 4% ` [dpdk-dev] [PATCH v3 0/9] Dynamic memzone Sergio Gonzalez Monroy
2015-06-19 17:21 1% ` [dpdk-dev] [PATCH v3 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
@ 2015-06-19 17:21 14% ` Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-19 17:21 UTC (permalink / raw)
To: dev
Announce the creation of dummy malloc library for 2.1 and removal of
such library, now integrated in librte_eal, for 2.2 release.
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
doc/guides/rel_notes/abi.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/guides/rel_notes/abi.rst b/doc/guides/rel_notes/abi.rst
index f00a6ee..2aaf900 100644
--- a/doc/guides/rel_notes/abi.rst
+++ b/doc/guides/rel_notes/abi.rst
@@ -38,3 +38,4 @@ Examples of Deprecation Notices
Deprecation Notices
-------------------
+* librte_malloc library has been integrated into librte_eal. The 2.1 release creates a dummy/empty malloc library to fulfill binaries with dynamic linking dependencies on librte_malloc.so. Such dummy library will not be created from release 2.2 so binaries will need to be rebuilt.
--
1.9.3
^ permalink raw reply [relevance 14%]
* [dpdk-dev] [PATCH v3 0/9] Dynamic memzone
@ 2015-06-19 17:21 4% ` Sergio Gonzalez Monroy
2015-06-19 17:21 1% ` [dpdk-dev] [PATCH v3 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-19 17:21 14% ` [dpdk-dev] [PATCH v3 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-25 14:05 4% ` [dpdk-dev] [PATCH v4 0/9] Dynamic memzone Sergio Gonzalez Monroy
` (2 subsequent siblings)
3 siblings, 2 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-19 17:21 UTC (permalink / raw)
To: dev
Current implemetation allows reserving/creating memzones but not the opposite
(unreserve/free). This affects mempools and other memzone based objects.
>From my point of view, implementing free functionality for memzones would look
like malloc over memsegs.
Thus, this approach moves malloc inside eal (which in turn removes a circular
dependency), where malloc heaps are composed of memsegs.
We keep both malloc and memzone APIs as they are, but memzones allocate its
memory by calling malloc_heap_alloc.
Some extra functionality is required in malloc to allow for boundary constrained
memory requests.
In summary, currently malloc is based on memzones, and with this approach
memzones are based on malloc.
v3:
- Create dummy librte_malloc
- Add deprecation notice
- Rework some of the code
- Doc update
- checkpatch
v2:
- New rte_memzone_free
- Support memzone len = 0
- Add all available memsegs to malloc heap at init
- Update memzone/malloc unit tests
Sergio Gonzalez Monroy (9):
eal: move librte_malloc to eal/common
eal: memzone allocated by malloc
app/test: update malloc/memzone unit tests
config: remove CONFIG_RTE_MALLOC_MEMZONE_SIZE
eal: remove free_memseg and references to it
eal: new rte_memzone_free
app/test: update unit test with rte_memzone_free
doc: announce ABI change of librte_malloc
doc: update malloc documentation
MAINTAINERS | 9 +-
app/test/test_malloc.c | 86 -----
app/test/test_memzone.c | 441 +++-------------------
config/common_bsdapp | 8 +-
config/common_linuxapp | 8 +-
doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++++++++-
doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 80952 bytes
doc/guides/prog_guide/index.rst | 1 -
doc/guides/prog_guide/malloc_lib.rst | 233 ------------
doc/guides/prog_guide/overview.rst | 11 +-
doc/guides/rel_notes/abi.rst | 1 +
drivers/net/af_packet/Makefile | 1 -
drivers/net/bonding/Makefile | 1 -
drivers/net/e1000/Makefile | 2 +-
drivers/net/enic/Makefile | 2 +-
drivers/net/fm10k/Makefile | 2 +-
drivers/net/i40e/Makefile | 2 +-
drivers/net/ixgbe/Makefile | 2 +-
drivers/net/mlx4/Makefile | 1 -
drivers/net/null/Makefile | 1 -
drivers/net/pcap/Makefile | 1 -
drivers/net/virtio/Makefile | 2 +-
drivers/net/vmxnet3/Makefile | 2 +-
drivers/net/xenvirt/Makefile | 2 +-
lib/Makefile | 2 +-
lib/librte_acl/Makefile | 2 +-
lib/librte_eal/bsdapp/eal/Makefile | 4 +-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 19 +
lib/librte_eal/common/Makefile | 1 +
lib/librte_eal/common/eal_common_memzone.c | 329 ++++++----------
lib/librte_eal/common/include/rte_eal_memconfig.h | 5 +-
lib/librte_eal/common/include/rte_malloc.h | 342 +++++++++++++++++
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/include/rte_memzone.h | 11 +
lib/librte_eal/common/malloc_elem.c | 344 +++++++++++++++++
lib/librte_eal/common/malloc_elem.h | 192 ++++++++++
lib/librte_eal/common/malloc_heap.c | 206 ++++++++++
lib/librte_eal/common/malloc_heap.h | 70 ++++
lib/librte_eal/common/rte_malloc.c | 259 +++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 4 +-
lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 +-
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 19 +
lib/librte_hash/Makefile | 2 +-
lib/librte_lpm/Makefile | 2 +-
lib/librte_malloc/Makefile | 6 +-
lib/librte_malloc/malloc_elem.c | 320 ----------------
lib/librte_malloc/malloc_elem.h | 190 ----------
lib/librte_malloc/malloc_heap.c | 209 ----------
lib/librte_malloc/malloc_heap.h | 70 ----
lib/librte_malloc/rte_malloc.c | 228 +----------
lib/librte_malloc/rte_malloc.h | 342 -----------------
lib/librte_malloc/rte_malloc_version.map | 16 -
lib/librte_mempool/Makefile | 2 -
lib/librte_port/Makefile | 1 -
lib/librte_ring/Makefile | 3 +-
lib/librte_table/Makefile | 1 -
56 files changed, 1897 insertions(+), 2363 deletions(-)
delete mode 100644 doc/guides/prog_guide/malloc_lib.rst
create mode 100644 lib/librte_eal/common/include/rte_malloc.h
create mode 100644 lib/librte_eal/common/malloc_elem.c
create mode 100644 lib/librte_eal/common/malloc_elem.h
create mode 100644 lib/librte_eal/common/malloc_heap.c
create mode 100644 lib/librte_eal/common/malloc_heap.h
create mode 100644 lib/librte_eal/common/rte_malloc.c
delete mode 100644 lib/librte_malloc/malloc_elem.c
delete mode 100644 lib/librte_malloc/malloc_elem.h
delete mode 100644 lib/librte_malloc/malloc_heap.c
delete mode 100644 lib/librte_malloc/malloc_heap.h
delete mode 100644 lib/librte_malloc/rte_malloc.h
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v3 2/9] eal: memzone allocated by malloc
2015-06-19 17:21 4% ` [dpdk-dev] [PATCH v3 0/9] Dynamic memzone Sergio Gonzalez Monroy
@ 2015-06-19 17:21 1% ` Sergio Gonzalez Monroy
2015-06-19 17:21 14% ` [dpdk-dev] [PATCH v3 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
1 sibling, 0 replies; 200+ results
From: Sergio Gonzalez Monroy @ 2015-06-19 17:21 UTC (permalink / raw)
To: dev
In the current memory hierarchy, memsegs are groups of physically
contiguous hugepages, memzones are slices of memsegs and malloc further
slices memzones into smaller memory chunks.
This patch modifies malloc so it partitions memsegs instead of memzones.
Thus memzones would call malloc internally for memory allocation while
maintaining its ABI.
It would be possible to free memzones and therefore any other structure
based on memzones, ie. mempools
Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
---
lib/librte_eal/common/eal_common_memzone.c | 274 ++++++----------------
lib/librte_eal/common/include/rte_eal_memconfig.h | 2 +-
lib/librte_eal/common/include/rte_malloc_heap.h | 3 +-
lib/librte_eal/common/malloc_elem.c | 68 ++++--
lib/librte_eal/common/malloc_elem.h | 14 +-
lib/librte_eal/common/malloc_heap.c | 139 ++++++-----
lib/librte_eal/common/malloc_heap.h | 6 +-
lib/librte_eal/common/rte_malloc.c | 7 +-
8 files changed, 196 insertions(+), 317 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index 888f9e5..943012b 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -50,15 +50,15 @@
#include <rte_string_fns.h>
#include <rte_common.h>
+#include "malloc_heap.h"
+#include "malloc_elem.h"
#include "eal_private.h"
-/* internal copy of free memory segments */
-static struct rte_memseg *free_memseg = NULL;
-
static inline const struct rte_memzone *
memzone_lookup_thread_unsafe(const char *name)
{
const struct rte_mem_config *mcfg;
+ const struct rte_memzone *mz;
unsigned i = 0;
/* get pointer to global configuration */
@@ -68,8 +68,9 @@ memzone_lookup_thread_unsafe(const char *name)
* the algorithm is not optimal (linear), but there are few
* zones and this function should be called at init only
*/
- for (i = 0; i < RTE_MAX_MEMZONE && mcfg->memzone[i].addr != NULL; i++) {
- if (!strncmp(name, mcfg->memzone[i].name, RTE_MEMZONE_NAMESIZE))
+ for (i = 0; i < RTE_MAX_MEMZONE; i++) {
+ mz = &mcfg->memzone[i];
+ if (mz->addr != NULL && !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE))
return &mcfg->memzone[i];
}
@@ -88,39 +89,45 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id,
len, socket_id, flags, RTE_CACHE_LINE_SIZE);
}
-/*
- * Helper function for memzone_reserve_aligned_thread_unsafe().
- * Calculate address offset from the start of the segment.
- * Align offset in that way that it satisfy istart alignmnet and
- * buffer of the requested length would not cross specified boundary.
- */
-static inline phys_addr_t
-align_phys_boundary(const struct rte_memseg *ms, size_t len, size_t align,
- size_t bound)
+/* Find the heap with the greatest free block size */
+static void
+find_heap_max_free_elem(int *s, size_t *len, unsigned align)
{
- phys_addr_t addr_offset, bmask, end, start;
- size_t step;
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- step = RTE_MAX(align, bound);
- bmask = ~((phys_addr_t)bound - 1);
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate offset to closest alignment */
- start = RTE_ALIGN_CEIL(ms->phys_addr, align);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size > *len) {
+ *len = stats.greatest_free_size;
+ *s = i;
+ }
+ }
+ *len -= (MALLOC_ELEM_OVERHEAD + align);
+}
- while (addr_offset + len < ms->len) {
+/* Find a heap that can allocate the requested size */
+static void
+find_heap_suitable(int *s, size_t len, unsigned align)
+{
+ struct rte_mem_config *mcfg;
+ struct rte_malloc_socket_stats stats;
+ unsigned i;
- /* check, do we meet boundary condition */
- end = start + len - (len != 0);
- if ((start & bmask) == (end & bmask))
- break;
+ /* get pointer to global configuration */
+ mcfg = rte_eal_get_configuration()->mem_config;
- /* calculate next offset */
- start = RTE_ALIGN_CEIL(start + 1, step);
- addr_offset = start - ms->phys_addr;
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats);
+ if (stats.greatest_free_size >= len + MALLOC_ELEM_OVERHEAD + align) {
+ *s = i;
+ break;
+ }
}
-
- return (addr_offset);
}
static const struct rte_memzone *
@@ -128,13 +135,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
int socket_id, unsigned flags, unsigned align, unsigned bound)
{
struct rte_mem_config *mcfg;
- unsigned i = 0;
- int memseg_idx = -1;
- uint64_t addr_offset, seg_offset = 0;
size_t requested_len;
- size_t memseg_len = 0;
- phys_addr_t memseg_physaddr;
- void *memseg_addr;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
@@ -166,7 +167,6 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
if (align < RTE_CACHE_LINE_SIZE)
align = RTE_CACHE_LINE_SIZE;
-
/* align length on cache boundary. Check for overflow before doing so */
if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) {
rte_errno = EINVAL; /* requested size too big */
@@ -180,129 +180,50 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len);
/* check that boundary condition is valid */
- if (bound != 0 &&
- (requested_len > bound || !rte_is_power_of_2(bound))) {
+ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) {
rte_errno = EINVAL;
return NULL;
}
- /* find the smallest segment matching requirements */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- /* last segment */
- if (free_memseg[i].addr == NULL)
- break;
+ if (len == 0) {
+ if (bound != 0)
+ requested_len = bound;
+ else
+ requested_len = 0;
+ }
- /* empty segment, skip it */
- if (free_memseg[i].len == 0)
- continue;
-
- /* bad socket ID */
- if (socket_id != SOCKET_ID_ANY &&
- free_memseg[i].socket_id != SOCKET_ID_ANY &&
- socket_id != free_memseg[i].socket_id)
- continue;
-
- /*
- * calculate offset to closest alignment that
- * meets boundary conditions.
- */
- addr_offset = align_phys_boundary(free_memseg + i,
- requested_len, align, bound);
-
- /* check len */
- if ((requested_len + addr_offset) > free_memseg[i].len)
- continue;
-
- /* check flags for hugepage sizes */
- if ((flags & RTE_MEMZONE_2MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_1G)
- continue;
- if ((flags & RTE_MEMZONE_1GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_2M)
- continue;
- if ((flags & RTE_MEMZONE_16MB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16G)
- continue;
- if ((flags & RTE_MEMZONE_16GB) &&
- free_memseg[i].hugepage_sz == RTE_PGSIZE_16M)
- continue;
-
- /* this segment is the best until now */
- if (memseg_idx == -1) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- /* find the biggest contiguous zone */
- else if (len == 0) {
- if (free_memseg[i].len > memseg_len) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
- }
- }
- /*
- * find the smallest (we already checked that current
- * zone length is > len
- */
- else if (free_memseg[i].len + align < memseg_len ||
- (free_memseg[i].len <= memseg_len + align &&
- addr_offset < seg_offset)) {
- memseg_idx = i;
- memseg_len = free_memseg[i].len;
- seg_offset = addr_offset;
+ if (socket_id == SOCKET_ID_ANY) {
+ if (requested_len == 0)
+ find_heap_max_free_elem(&socket_id, &requested_len, align);
+ else
+ find_heap_suitable(&socket_id, requested_len, align);
+
+ if (socket_id == SOCKET_ID_ANY) {
+ rte_errno = ENOMEM;
+ return NULL;
}
}
- /* no segment found */
- if (memseg_idx == -1) {
- /*
- * If RTE_MEMZONE_SIZE_HINT_ONLY flag is specified,
- * try allocating again without the size parameter otherwise -fail.
- */
- if ((flags & RTE_MEMZONE_SIZE_HINT_ONLY) &&
- ((flags & RTE_MEMZONE_1GB) || (flags & RTE_MEMZONE_2MB)
- || (flags & RTE_MEMZONE_16MB) || (flags & RTE_MEMZONE_16GB)))
- return memzone_reserve_aligned_thread_unsafe(name,
- len, socket_id, 0, align, bound);
-
+ /* allocate memory on heap */
+ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket_id], NULL,
+ requested_len, flags, align, bound);
+ if (mz_addr == NULL) {
rte_errno = ENOMEM;
return NULL;
}
- /* save aligned physical and virtual addresses */
- memseg_physaddr = free_memseg[memseg_idx].phys_addr + seg_offset;
- memseg_addr = RTE_PTR_ADD(free_memseg[memseg_idx].addr,
- (uintptr_t) seg_offset);
-
- /* if we are looking for a biggest memzone */
- if (len == 0) {
- if (bound == 0)
- requested_len = memseg_len - seg_offset;
- else
- requested_len = RTE_ALIGN_CEIL(memseg_physaddr + 1,
- bound) - memseg_physaddr;
- }
-
- /* set length to correct value */
- len = (size_t)seg_offset + requested_len;
-
- /* update our internal state */
- free_memseg[memseg_idx].len -= len;
- free_memseg[memseg_idx].phys_addr += len;
- free_memseg[memseg_idx].addr =
- (char *)free_memseg[memseg_idx].addr + len;
+ const struct malloc_elem *elem = malloc_elem_from_data(mz_addr);
/* fill the zone in config */
struct rte_memzone *mz = &mcfg->memzone[mcfg->memzone_idx++];
snprintf(mz->name, sizeof(mz->name), "%s", name);
- mz->phys_addr = memseg_physaddr;
- mz->addr = memseg_addr;
- mz->len = requested_len;
- mz->hugepage_sz = free_memseg[memseg_idx].hugepage_sz;
- mz->socket_id = free_memseg[memseg_idx].socket_id;
+ mz->phys_addr = rte_malloc_virt2phy(mz_addr);
+ mz->addr = mz_addr;
+ mz->len = (requested_len == 0 ? elem->size : requested_len);
+ mz->hugepage_sz = elem->ms->hugepage_sz;
+ mz->socket_id = elem->ms->socket_id;
mz->flags = 0;
- mz->memseg_id = memseg_idx;
+ mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg;
return mz;
}
@@ -419,45 +340,6 @@ rte_memzone_dump(FILE *f)
}
/*
- * called by init: modify the free memseg list to have cache-aligned
- * addresses and cache-aligned lengths
- */
-static int
-memseg_sanitize(struct rte_memseg *memseg)
-{
- unsigned phys_align;
- unsigned virt_align;
- unsigned off;
-
- phys_align = memseg->phys_addr & RTE_CACHE_LINE_MASK;
- virt_align = (unsigned long)memseg->addr & RTE_CACHE_LINE_MASK;
-
- /*
- * sanity check: phys_addr and addr must have the same
- * alignment
- */
- if (phys_align != virt_align)
- return -1;
-
- /* memseg is really too small, don't bother with it */
- if (memseg->len < (2 * RTE_CACHE_LINE_SIZE)) {
- memseg->len = 0;
- return 0;
- }
-
- /* align start address */
- off = (RTE_CACHE_LINE_SIZE - phys_align) & RTE_CACHE_LINE_MASK;
- memseg->phys_addr += off;
- memseg->addr = (char *)memseg->addr + off;
- memseg->len -= off;
-
- /* align end address */
- memseg->len &= ~((uint64_t)RTE_CACHE_LINE_MASK);
-
- return 0;
-}
-
-/*
* Init the memzone subsystem
*/
int
@@ -465,14 +347,10 @@ rte_eal_memzone_init(void)
{
struct rte_mem_config *mcfg;
const struct rte_memseg *memseg;
- unsigned i = 0;
/* get pointer to global configuration */
mcfg = rte_eal_get_configuration()->mem_config;
- /* mirror the runtime memsegs from config */
- free_memseg = mcfg->free_memseg;
-
/* secondary processes don't need to initialise anything */
if (rte_eal_process_type() == RTE_PROC_SECONDARY)
return 0;
@@ -485,33 +363,13 @@ rte_eal_memzone_init(void)
rte_rwlock_write_lock(&mcfg->mlock);
- /* fill in uninitialized free_memsegs */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (memseg[i].addr == NULL)
- break;
- if (free_memseg[i].addr != NULL)
- continue;
- memcpy(&free_memseg[i], &memseg[i], sizeof(struct rte_memseg));
- }
-
- /* make all zones cache-aligned */
- for (i = 0; i < RTE_MAX_MEMSEG; i++) {
- if (free_memseg[i].addr == NULL)
- break;
- if (memseg_sanitize(&free_memseg[i]) < 0) {
- RTE_LOG(ERR, EAL, "%s(): Sanity check failed\n", __func__);
- rte_rwlock_write_unlock(&mcfg->mlock);
- return -1;
- }
- }
-
/* delete all zones */
mcfg->memzone_idx = 0;
memset(mcfg->memzone, 0, sizeof(mcfg->memzone));
rte_rwlock_write_unlock(&mcfg->mlock);
- return 0;
+ return rte_eal_malloc_heap_init();
}
/* Walk all reserved memory zones */
diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 34f5abc..055212a 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -73,7 +73,7 @@ struct rte_mem_config {
struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */
struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */
- /* Runtime Physmem descriptors. */
+ /* Runtime Physmem descriptors - NOT USED */
struct rte_memseg free_memseg[RTE_MAX_MEMSEG];
struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */
diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h
index 716216f..b270356 100644
--- a/lib/librte_eal/common/include/rte_malloc_heap.h
+++ b/lib/librte_eal/common/include/rte_malloc_heap.h
@@ -40,7 +40,7 @@
#include <rte_memory.h>
/* Number of free lists per heap, grouped by size. */
-#define RTE_HEAP_NUM_FREELISTS 5
+#define RTE_HEAP_NUM_FREELISTS 13
/**
* Structure to hold malloc heap
@@ -48,7 +48,6 @@
struct malloc_heap {
rte_spinlock_t lock;
LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS];
- unsigned mz_count;
unsigned alloc_count;
size_t total_size;
} __rte_cache_aligned;
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index a5e1248..b54ee33 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -37,7 +37,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include <rte_per_lcore.h>
@@ -56,10 +55,10 @@
*/
void
malloc_elem_init(struct malloc_elem *elem,
- struct malloc_heap *heap, const struct rte_memzone *mz, size_t size)
+ struct malloc_heap *heap, const struct rte_memseg *ms, size_t size)
{
elem->heap = heap;
- elem->mz = mz;
+ elem->ms = ms;
elem->prev = NULL;
memset(&elem->free_list, 0, sizeof(elem->free_list));
elem->state = ELEM_FREE;
@@ -70,12 +69,12 @@ malloc_elem_init(struct malloc_elem *elem,
}
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
{
- malloc_elem_init(elem, prev->heap, prev->mz, 0);
+ malloc_elem_init(elem, prev->heap, prev->ms, 0);
elem->prev = prev;
elem->state = ELEM_BUSY; /* mark busy so its never merged */
}
@@ -86,12 +85,24 @@ malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
* fit, return NULL.
*/
static void *
-elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
+elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- const uintptr_t end_pt = (uintptr_t)elem +
+ const size_t bmask = ~(bound - 1);
+ uintptr_t end_pt = (uintptr_t)elem +
elem->size - MALLOC_ELEM_TRAILER_LEN;
- const uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
- const uintptr_t new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
+ uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ uintptr_t new_elem_start;
+
+ /* check boundary */
+ if ((new_data_start & bmask) != ((end_pt - 1) & bmask)) {
+ end_pt = RTE_ALIGN_FLOOR(end_pt, bound);
+ new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align);
+ if (((end_pt - 1) & bmask) != (new_data_start & bmask))
+ return NULL;
+ }
+
+ new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN;
/* if the new start point is before the exist start, it won't fit */
return (new_elem_start < (uintptr_t)elem) ? NULL : (void *)new_elem_start;
@@ -102,9 +113,10 @@ elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align)
* alignment request from the current element
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- return elem_start_pt(elem, size, align) != NULL;
+ return elem_start_pt(elem, size, align, bound) != NULL;
}
/*
@@ -115,10 +127,10 @@ static void
split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)
{
struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size);
- const unsigned old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
- const unsigned new_elem_size = elem->size - old_elem_size;
+ const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
+ const size_t new_elem_size = elem->size - old_elem_size;
- malloc_elem_init(split_pt, elem->heap, elem->mz, new_elem_size);
+ malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size);
split_pt->prev = elem;
next_elem->prev = split_pt;
elem->size = old_elem_size;
@@ -168,8 +180,9 @@ malloc_elem_free_list_index(size_t size)
void
malloc_elem_free_list_insert(struct malloc_elem *elem)
{
- size_t idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
+ size_t idx;
+ idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN);
elem->state = ELEM_FREE;
LIST_INSERT_HEAD(&elem->heap->free_head[idx], elem, free_list);
}
@@ -190,12 +203,26 @@ elem_free_list_remove(struct malloc_elem *elem)
* is not done here, as it's done there previously.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
+malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,
+ size_t bound)
{
- struct malloc_elem *new_elem = elem_start_pt(elem, size, align);
- const unsigned old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound);
+ const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem;
+ const size_t trailer_size = elem->size - old_elem_size - size -
+ MALLOC_ELEM_OVERHEAD;
+
+ elem_free_list_remove(elem);
- if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE){
+ if (trailer_size > MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* split it, too much free space after elem */
+ struct malloc_elem *new_free_elem =
+ RTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD);
+
+ split_elem(elem, new_free_elem);
+ malloc_elem_free_list_insert(new_free_elem);
+ }
+
+ if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
/* don't split it, pad the element instead */
elem->state = ELEM_BUSY;
elem->pad = old_elem_size;
@@ -208,8 +235,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
new_elem->size = elem->size - elem->pad;
set_header(new_elem);
}
- /* remove element from free list */
- elem_free_list_remove(elem);
return new_elem;
}
@@ -219,7 +244,6 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align)
* Re-insert original element, in case its new size makes it
* belong on a different list.
*/
- elem_free_list_remove(elem);
split_elem(elem, new_elem);
new_elem->state = ELEM_BUSY;
malloc_elem_free_list_insert(elem);
diff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h
index 9790b1a..e05d2ea 100644
--- a/lib/librte_eal/common/malloc_elem.h
+++ b/lib/librte_eal/common/malloc_elem.h
@@ -47,9 +47,9 @@ enum elem_state {
struct malloc_elem {
struct malloc_heap *heap;
- struct malloc_elem *volatile prev; /* points to prev elem in memzone */
+ struct malloc_elem *volatile prev; /* points to prev elem in memseg */
LIST_ENTRY(malloc_elem) free_list; /* list of free elements in heap */
- const struct rte_memzone *mz;
+ const struct rte_memseg *ms;
volatile enum elem_state state;
uint32_t pad;
size_t size;
@@ -136,11 +136,11 @@ malloc_elem_from_data(const void *data)
void
malloc_elem_init(struct malloc_elem *elem,
struct malloc_heap *heap,
- const struct rte_memzone *mz,
+ const struct rte_memseg *ms,
size_t size);
/*
- * initialise a dummy malloc_elem header for the end-of-memzone marker
+ * initialise a dummy malloc_elem header for the end-of-memseg marker
*/
void
malloc_elem_mkend(struct malloc_elem *elem,
@@ -151,14 +151,16 @@ malloc_elem_mkend(struct malloc_elem *elem,
* of the requested size and with the requested alignment
*/
int
-malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_can_hold(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* reserve a block of data in an existing malloc_elem. If the malloc_elem
* is much larger than the data block requested, we split the element in two.
*/
struct malloc_elem *
-malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align);
+malloc_elem_alloc(struct malloc_elem *elem, size_t size,
+ unsigned align, size_t bound);
/*
* free a malloc_elem block by adding it to the free list. If the
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index defb903..f5fff96 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -39,7 +39,6 @@
#include <sys/queue.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_launch.h>
@@ -54,123 +53,104 @@
#include "malloc_elem.h"
#include "malloc_heap.h"
-/* since the memzone size starts with a digit, it will appear unquoted in
- * rte_config.h, so quote it so it can be passed to rte_str_to_size */
-#define MALLOC_MEMZONE_SIZE RTE_STR(RTE_MALLOC_MEMZONE_SIZE)
-
-/*
- * returns the configuration setting for the memzone size as a size_t value
- */
-static inline size_t
-get_malloc_memzone_size(void)
+static unsigned
+check_hugepage_sz(unsigned flags, size_t hugepage_sz)
{
- return rte_str_to_size(MALLOC_MEMZONE_SIZE);
+ unsigned ret = 1;
+
+ if ((flags & RTE_MEMZONE_2MB) && hugepage_sz == RTE_PGSIZE_1G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_1GB) && hugepage_sz == RTE_PGSIZE_2M)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16MB) && hugepage_sz == RTE_PGSIZE_16G)
+ ret = 0;
+ if ((flags & RTE_MEMZONE_16GB) && hugepage_sz == RTE_PGSIZE_16M)
+ ret = 0;
+
+ return ret;
}
/*
- * reserve an extra memory zone and make it available for use by a particular
- * heap. This reserves the zone and sets a dummy malloc_elem header at the end
+ * Expand the heap with a memseg.
+ * This reserves the zone and sets a dummy malloc_elem header at the end
* to prevent overflow. The rest of the zone is added to free list as a single
* large free block
*/
-static int
-malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
+static void
+malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)
{
- const unsigned mz_flags = 0;
- const size_t block_size = get_malloc_memzone_size();
- /* ensure the data we want to allocate will fit in the memzone */
- const size_t min_size = size + align + MALLOC_ELEM_OVERHEAD * 2;
- const struct rte_memzone *mz = NULL;
- struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
- unsigned numa_socket = heap - mcfg->malloc_heaps;
-
- size_t mz_size = min_size;
- if (mz_size < block_size)
- mz_size = block_size;
-
- char mz_name[RTE_MEMZONE_NAMESIZE];
- snprintf(mz_name, sizeof(mz_name), "MALLOC_S%u_HEAP_%u",
- numa_socket, heap->mz_count++);
-
- /* try getting a block. if we fail and we don't need as big a block
- * as given in the config, we can shrink our request and try again
- */
- do {
- mz = rte_memzone_reserve(mz_name, mz_size, numa_socket,
- mz_flags);
- if (mz == NULL)
- mz_size /= 2;
- } while (mz == NULL && mz_size > min_size);
- if (mz == NULL)
- return -1;
-
/* allocate the memory block headers, one at end, one at start */
- struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
- struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
- mz_size - MALLOC_ELEM_OVERHEAD);
+ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr;
+ struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr,
+ ms->len - MALLOC_ELEM_OVERHEAD);
end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);
+ const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
- malloc_elem_init(start_elem, heap, mz, elem_size);
+ malloc_elem_init(start_elem, heap, ms, elem_size);
malloc_elem_mkend(end_elem, start_elem);
malloc_elem_free_list_insert(start_elem);
- /* increase heap total size by size of new memzone */
- heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
- return 0;
+ heap->total_size += elem_size;
}
/*
* Iterates through the freelist for a heap to find a free element
* which can store data of the required size and with the requested alignment.
+ * If size is 0, find the biggest available elem.
* Returns null on failure, or pointer to element on success.
*/
static struct malloc_elem *
-find_suitable_element(struct malloc_heap *heap, size_t size, unsigned align)
+find_suitable_element(struct malloc_heap *heap, size_t size,
+ unsigned flags, size_t align, size_t bound)
{
size_t idx;
- struct malloc_elem *elem;
+ struct malloc_elem *elem, *alt_elem = NULL;
for (idx = malloc_elem_free_list_index(size);
- idx < RTE_HEAP_NUM_FREELISTS; idx++)
- {
+ idx < RTE_HEAP_NUM_FREELISTS; idx++) {
for (elem = LIST_FIRST(&heap->free_head[idx]);
- !!elem; elem = LIST_NEXT(elem, free_list))
- {
- if (malloc_elem_can_hold(elem, size, align))
- return elem;
+ !!elem; elem = LIST_NEXT(elem, free_list)) {
+ if (malloc_elem_can_hold(elem, size, align, bound)) {
+ if (check_hugepage_sz(flags, elem->ms->hugepage_sz))
+ return elem;
+ alt_elem = elem;
+ }
}
}
+
+ if ((alt_elem != NULL) && (flags & RTE_MEMZONE_SIZE_HINT_ONLY))
+ return alt_elem;
+
return NULL;
}
/*
- * Main function called by malloc to allocate a block of memory from the
- * heap. It locks the free list, scans it, and adds a new memzone if the
- * scan fails. Once the new memzone is added, it re-scans and should return
+ * Main function to allocate a block of memory from the heap.
+ * It locks the free list, scans it, and adds a new memseg if the
+ * scan fails. Once the new memseg is added, it re-scans and should return
* the new element after releasing the lock.
*/
void *
malloc_heap_alloc(struct malloc_heap *heap,
- const char *type __attribute__((unused)), size_t size, unsigned align)
+ const char *type __attribute__((unused)), size_t size, unsigned flags,
+ size_t align, size_t bound)
{
+ struct malloc_elem *elem;
+
size = RTE_CACHE_LINE_ROUNDUP(size);
align = RTE_CACHE_LINE_ROUNDUP(align);
+
rte_spinlock_lock(&heap->lock);
- struct malloc_elem *elem = find_suitable_element(heap, size, align);
- if (elem == NULL){
- if ((malloc_heap_add_memzone(heap, size, align)) == 0)
- elem = find_suitable_element(heap, size, align);
- }
- if (elem != NULL){
- elem = malloc_elem_alloc(elem, size, align);
+ elem = find_suitable_element(heap, size, flags, align, bound);
+ if (elem != NULL) {
+ elem = malloc_elem_alloc(elem, size, align, bound);
/* increase heap's count of allocated elements */
heap->alloc_count++;
}
rte_spinlock_unlock(&heap->lock);
- return elem == NULL ? NULL : (void *)(&elem[1]);
+ return elem == NULL ? NULL : (void *)(&elem[1]);
}
/*
@@ -207,3 +187,20 @@ malloc_heap_get_stats(const struct malloc_heap *heap,
return 0;
}
+int
+rte_eal_malloc_heap_init(void)
+{
+ struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+ unsigned ms_cnt;
+ struct rte_memseg *ms;
+
+ if (mcfg == NULL)
+ return -1;
+
+ for (ms = &mcfg->memseg[0], ms_cnt = 0;
+ (ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0);
+ ms_cnt++, ms++)
+ malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms);
+
+ return 0;
+}
diff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h
index a47136d..3ccbef0 100644
--- a/lib/librte_eal/common/malloc_heap.h
+++ b/lib/librte_eal/common/malloc_heap.h
@@ -53,15 +53,15 @@ malloc_get_numa_socket(void)
}
void *
-malloc_heap_alloc(struct malloc_heap *heap, const char *type,
- size_t size, unsigned align);
+malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size,
+ unsigned flags, size_t align, size_t bound);
int
malloc_heap_get_stats(const struct malloc_heap *heap,
struct rte_malloc_socket_stats *socket_stats);
int
-rte_eal_heap_memzone_init(void);
+rte_eal_malloc_heap_init(void);
#ifdef __cplusplus
}
diff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c
index c313a57..54c2bd8 100644
--- a/lib/librte_eal/common/rte_malloc.c
+++ b/lib/librte_eal/common/rte_malloc.c
@@ -39,7 +39,6 @@
#include <rte_memcpy.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_eal_memconfig.h>
#include <rte_branch_prediction.h>
@@ -87,7 +86,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
return NULL;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL || socket_arg != SOCKET_ID_ANY)
return ret;
@@ -98,7 +97,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)
continue;
ret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type,
- size, align == 0 ? 1 : align);
+ size, 0, align == 0 ? 1 : align, 0);
if (ret != NULL)
return ret;
}
@@ -256,5 +255,5 @@ rte_malloc_virt2phy(const void *addr)
const struct malloc_elem *elem = malloc_elem_from_data(addr);
if (elem == NULL)
return 0;
- return elem->mz->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->mz->addr);
+ return elem->ms->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->ms->addr);
}
--
1.9.3
^ permalink raw reply [relevance 1%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 16:13 9% ` Thomas F Herbert
@ 2015-06-19 17:02 8% ` Thomas Monjalon
2015-06-19 17:57 9% ` Thomas F Herbert
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-19 17:02 UTC (permalink / raw)
To: Thomas F Herbert; +Cc: dev
2015-06-19 12:13, Thomas F Herbert:
>
> On 6/19/15 9:16 AM, Thomas Monjalon wrote:
> > 2015-06-19 09:02, Neil Horman:
> >> On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
> >>> 2015-06-19 06:26, Neil Horman:
> >>>> On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> >>>>> For the 2.1 release, I think we should agree to make patches that change
> >>>>> the ABI controllable via a compile-time option. I like Olivier's proposal
> >>>>> on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
> >>>>> changes instead of a separate option per patch set (see
> >>>>> http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
> >>>>> should rework the affected patch sets to use that approach for 2.1.
> >>>>
> >>>> This is a bad idea. Making ABI dependent on compile time options isn't a
> >>>> maintainable solution. It breaks the notion of how LIBABIVER is supposed to
> >>>> work (that is to say you make it impossible to really tell what ABI version you
> >>>> are building).
> >>>
> >>> The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
> >>> So one ABI version number refers always to the same ABI.
> >>>
> >>>> If you have two compile time options that modify the ABI, you
> >>>> have to burn through 4 possible LIBABIVER version values to accomodate all
> >>>> possible combinations, and then you need to remember that when you make them
> >>>> statically applicable.
> >>>
> >>> The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
> >>>
> >>> Your intent when introducing ABI policy was to allow smooth porting of
> >>> applications from a DPDK version to another. Right?
> >>> The adopted solution was to provide backward compatibility during 1 release.
> >>> But there are cases where it's not possible. So the policy was to notice
> >>> the future change and wait one release cycle to break the ABI (failing
> >>> compatibility goals).
> >>> The compile-time option may provide an alternative DPDK packaging when the
> >>> ABI backward compatibility cannot be provided (case of mbuf changes).
> >>> In such case, it's still possible to upgrade DPDK by providing 2 versions of
> >>> DPDK libs. So the existing apps continue to link with the previous ABI and
> >>> have the possibility of migrating to the new one.
> >>> Another advantage of this approach is that we don't have to wait 1 release
> >>> to integrate the changes.
> >>> The last advantage is to benefit early of these changes with static libraries.
> >>
> >> Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
> >> Implementing an ABI preview option like this implies the notion that, after a
> >> release, you have to remove all the ifdefs that you inserted to create the new
> >> ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
> >> large, and is predicated on the centralization of work effort (that is to say
> >> you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
> >> from the build' patch every release.
> >
> > It won't be so huge if we reserve the NEXT_ABI solution to changes which cannot
> > have easy backward compatibility with the compat macros you introduced.
> > I feel I can do the job of removing the ifdefs NEXT_ABI after each release.
> > At the same time, the deprecated API, using the compat macros, will be removed.
> >
> >> What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
> >> the sort that Thomas Herbert proposed a few weeks ago).
> >
> > This tree was created after Thomas' request:
> > http://dpdk.org/browse/next/dpdk-next/
>
> Thomas, I am sorry if I went quiet for awhile but I was on personal
> travel with inconsistent access so I almost missed most of this
> discussion about ABI changes.
>
> My understanding of the purpose of the dpdk-next tree is to validate
> patches by applying and compiling against a "pull" from the main dpdk
> tree. I think a good way to handle ABI change while effectively using
> the dpdk-next might be to do as follows:
>
> Create a specific branch for the new ABI such as 2.X in the main dpdk
> tree. Once that 2.X branch is created, dpdk-next would mirror the 2.X
> branch along with master.
>
> Since, dpdk-next would also have the 2.X branch that is in the main dpdk
> tree, submitted patches could be applied to either the main branch or
> the new-ABI 2.X branch. Providing that patch submitters make it clear
> whether a submitted patch is for the new ABI or the old ABI, dpdk-next
> could continue to validate the patches for either the main branch or the
> new ABI 2.X branch.
What is the benefit of a new-ABI branch in the -next tree?
The goal of this discussion is to find a consensus on ABI policy to
smoothly integrate new features without forcing users of shared libraries
to re-build their application when upgrading DPDK, and let them do the
transition before the next upgrade.
^ permalink raw reply [relevance 8%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 13:16 4% ` Thomas Monjalon
2015-06-19 15:27 9% ` Neil Horman
@ 2015-06-19 16:13 9% ` Thomas F Herbert
2015-06-19 17:02 8% ` Thomas Monjalon
1 sibling, 1 reply; 200+ results
From: Thomas F Herbert @ 2015-06-19 16:13 UTC (permalink / raw)
To: Thomas Monjalon, Neil Horman; +Cc: dev
On 6/19/15 9:16 AM, Thomas Monjalon wrote:
> 2015-06-19 09:02, Neil Horman:
>> On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
>>> 2015-06-19 06:26, Neil Horman:
>>>> On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
>>>>> For the 2.1 release, I think we should agree to make patches that change
>>>>> the ABI controllable via a compile-time option. I like Olivier's proposal
>>>>> on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
>>>>> changes instead of a separate option per patch set (see
>>>>> http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
>>>>> should rework the affected patch sets to use that approach for 2.1.
>>>>
>>>> This is a bad idea. Making ABI dependent on compile time options isn't a
>>>> maintainable solution. It breaks the notion of how LIBABIVER is supposed to
>>>> work (that is to say you make it impossible to really tell what ABI version you
>>>> are building).
>>>
>>> The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
>>> So one ABI version number refers always to the same ABI.
>>>
>>>> If you have two compile time options that modify the ABI, you
>>>> have to burn through 4 possible LIBABIVER version values to accomodate all
>>>> possible combinations, and then you need to remember that when you make them
>>>> statically applicable.
>>>
>>> The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
>>>
>>> Your intent when introducing ABI policy was to allow smooth porting of
>>> applications from a DPDK version to another. Right?
>>> The adopted solution was to provide backward compatibility during 1 release.
>>> But there are cases where it's not possible. So the policy was to notice
>>> the future change and wait one release cycle to break the ABI (failing
>>> compatibility goals).
>>> The compile-time option may provide an alternative DPDK packaging when the
>>> ABI backward compatibility cannot be provided (case of mbuf changes).
>>> In such case, it's still possible to upgrade DPDK by providing 2 versions of
>>> DPDK libs. So the existing apps continue to link with the previous ABI and
>>> have the possibility of migrating to the new one.
>>> Another advantage of this approach is that we don't have to wait 1 release
>>> to integrate the changes.
>>> The last advantage is to benefit early of these changes with static libraries.
>>
>> Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
>> Implementing an ABI preview option like this implies the notion that, after a
>> release, you have to remove all the ifdefs that you inserted to create the new
>> ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
>> large, and is predicated on the centralization of work effort (that is to say
>> you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
>> from the build' patch every release.
>
> It won't be so huge if we reserve the NEXT_ABI solution to changes which cannot
> have easy backward compatibility with the compat macros you introduced.
> I feel I can do the job of removing the ifdefs NEXT_ABI after each release.
> At the same time, the deprecated API, using the compat macros, will be removed.
>
>> What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
>> the sort that Thomas Herbert proposed a few weeks ago).
>
> This tree was created after Thomas' request:
> http://dpdk.org/browse/next/dpdk-next/
Thomas, I am sorry if I went quiet for awhile but I was on personal
travel with inconsistent access so I almost missed most of this
discussion about ABI changes.
My understanding of the purpose of the dpdk-next tree is to validate
patches by applying and compiling against a "pull" from the main dpdk
tree. I think a good way to handle ABI change while effectively using
the dpdk-next might be to do as follows:
Create a specific branch for the new ABI such as 2.X in the main dpdk
tree. Once that 2.X branch is created, dpdk-next would mirror the 2.X
branch along with master.
Since, dpdk-next would also have the 2.X branch that is in the main dpdk
tree, submitted patches could be applied to either the main branch or
the new-ABI 2.X branch. Providing that patch submitters make it clear
whether a submitted patch is for the new ABI or the old ABI, dpdk-next
could continue to validate the patches for either the main branch or the
new ABI 2.X branch.
>
>> Patches that aren't ABI stable can be put on the next-branch/tree in thier
>> final format. You can delcare the branch unstable (thereby reserving your
>> right to rebase it). People can use that to preview the next ABI version
>> (complete with the update LIBABIVER bump), and when you release dpdk-X,
>> the new ABI for dpdk-X+1 is achieved by simply merging.
>
> Having this tree living would be a nice improvement but it won't provide any
> stable (and enough validated) releases to rely on.
>
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 15:27 9% ` Neil Horman
@ 2015-06-19 15:51 9% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-06-19 15:51 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-19 11:27, Neil Horman:
> On Fri, Jun 19, 2015 at 03:16:53PM +0200, Thomas Monjalon wrote:
> > 2015-06-19 09:02, Neil Horman:
> > > On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
> > > > 2015-06-19 06:26, Neil Horman:
> > > > > On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> > > > > > For the 2.1 release, I think we should agree to make patches that change
> > > > > > the ABI controllable via a compile-time option. I like Olivier's proposal
> > > > > > on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
> > > > > > changes instead of a separate option per patch set (see
> > > > > > http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
> > > > > > should rework the affected patch sets to use that approach for 2.1.
> > > > >
> > > > > This is a bad idea. Making ABI dependent on compile time options isn't a
> > > > > maintainable solution. It breaks the notion of how LIBABIVER is supposed to
> > > > > work (that is to say you make it impossible to really tell what ABI version you
> > > > > are building).
> > > >
> > > > The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
> > > > So one ABI version number refers always to the same ABI.
> > > >
> > > > > If you have two compile time options that modify the ABI, you
> > > > > have to burn through 4 possible LIBABIVER version values to accomodate all
> > > > > possible combinations, and then you need to remember that when you make them
> > > > > statically applicable.
> > > >
> > > > The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
> > > >
> > > > Your intent when introducing ABI policy was to allow smooth porting of
> > > > applications from a DPDK version to another. Right?
> > > > The adopted solution was to provide backward compatibility during 1 release.
> > > > But there are cases where it's not possible. So the policy was to notice
> > > > the future change and wait one release cycle to break the ABI (failing
> > > > compatibility goals).
> > > > The compile-time option may provide an alternative DPDK packaging when the
> > > > ABI backward compatibility cannot be provided (case of mbuf changes).
> > > > In such case, it's still possible to upgrade DPDK by providing 2 versions of
> > > > DPDK libs. So the existing apps continue to link with the previous ABI and
> > > > have the possibility of migrating to the new one.
> > > > Another advantage of this approach is that we don't have to wait 1 release
> > > > to integrate the changes.
> > > > The last advantage is to benefit early of these changes with static libraries.
> > >
> > > Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
> > > Implementing an ABI preview option like this implies the notion that, after a
> > > release, you have to remove all the ifdefs that you inserted to create the new
> > > ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
> > > large, and is predicated on the centralization of work effort (that is to say
> > > you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
> > > from the build' patch every release.
> >
> > It won't be so huge if we reserve the NEXT_ABI solution to changes which cannot
> > have easy backward compatibility with the compat macros you introduced.
> > I feel I can do the job of removing the ifdefs NEXT_ABI after each release.
> > At the same time, the deprecated API, using the compat macros, will be removed.
> >
> I think that is something you can't really predict, as its not an issue of how
> stringent we are with its use, but rather a function of how much change
> developers want in a given release. That is to say, if you only reserve it for
> the most important/urgently needed changes, thats fine, but if you have a
> release in which 50 developers want to make urgent and important changes that
> breaks ABI, you still have quite a job on your hands to back out the config
> changes.
>
> Not to mention the fact that backing those changes out is a manual process.
>
> > > What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
> > > the sort that Thomas Herbert proposed a few weeks ago).
> >
> > This tree was created after Thomas' request:
> > http://dpdk.org/browse/next/dpdk-next/
> >
> Awesome, Though I'm not sure thats entirely the right place either. IIRC that
> location was intended to be an early integration site that took unreviewed
> patches. I think this really calls for a branch from the mainline tree that
> exclusively accepts reviewed ABI changing patches, that can then be merged after
> the next release
>
> > > Patches that aren't ABI stable can be put on the next-branch/tree in thier
> > > final format. You can delcare the branch unstable (thereby reserving your
> > > right to rebase it). People can use that to preview the next ABI version
> > > (complete with the update LIBABIVER bump), and when you release dpdk-X,
> > > the new ABI for dpdk-X+1 is achieved by simply merging.
> >
> > Having this tree living would be a nice improvement but it won't provide any
> > stable (and enough validated) releases to rely on.
> >
> I'm not sure I follow you entirely here. If the goal is to find a place to
> accept patches that are ABI altering ahead of the main release, why do you need
> to provide stable/validated releases? Just base it off the HEAD of the git tree
> during the DPDK release X merge window, any testing done in the base branch
> should roughly apply, save for functional changes made by the ABI patches you
> add in on the branch.
OK, I didn't get you. So you are saying that the changes for the next release
may be prepared in a branch. Yes, it's possible.
But before stating on practical method to execute the policy, we need to agree
on the policy.
This is my proposal:
- The ABI policy must be better explained: what happens to LIBABIVER and .map
when adding a field, adding or removing a function.
- The file doc/guides/rel_notes/abi.rst must contain the ABI notices but the
policy must be moved to doc/guides/guidelines/compat.rst
- The case "backward compatibility broken" must be replaced by the usage of
CONFIG_RTE_NEXT_ABI while describing cases where it can apply.
- The .map files must be generated in order to make it simpler and allows
the use of CONFIG_RTE_NEXT_ABI.
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 13:16 4% ` Thomas Monjalon
@ 2015-06-19 15:27 9% ` Neil Horman
2015-06-19 15:51 9% ` Thomas Monjalon
2015-06-19 16:13 9% ` Thomas F Herbert
1 sibling, 1 reply; 200+ results
From: Neil Horman @ 2015-06-19 15:27 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Fri, Jun 19, 2015 at 03:16:53PM +0200, Thomas Monjalon wrote:
> 2015-06-19 09:02, Neil Horman:
> > On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
> > > 2015-06-19 06:26, Neil Horman:
> > > > On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> > > > > For the 2.1 release, I think we should agree to make patches that change
> > > > > the ABI controllable via a compile-time option. I like Olivier's proposal
> > > > > on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
> > > > > changes instead of a separate option per patch set (see
> > > > > http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
> > > > > should rework the affected patch sets to use that approach for 2.1.
> > > >
> > > > This is a bad idea. Making ABI dependent on compile time options isn't a
> > > > maintainable solution. It breaks the notion of how LIBABIVER is supposed to
> > > > work (that is to say you make it impossible to really tell what ABI version you
> > > > are building).
> > >
> > > The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
> > > So one ABI version number refers always to the same ABI.
> > >
> > > > If you have two compile time options that modify the ABI, you
> > > > have to burn through 4 possible LIBABIVER version values to accomodate all
> > > > possible combinations, and then you need to remember that when you make them
> > > > statically applicable.
> > >
> > > The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
> > >
> > > Your intent when introducing ABI policy was to allow smooth porting of
> > > applications from a DPDK version to another. Right?
> > > The adopted solution was to provide backward compatibility during 1 release.
> > > But there are cases where it's not possible. So the policy was to notice
> > > the future change and wait one release cycle to break the ABI (failing
> > > compatibility goals).
> > > The compile-time option may provide an alternative DPDK packaging when the
> > > ABI backward compatibility cannot be provided (case of mbuf changes).
> > > In such case, it's still possible to upgrade DPDK by providing 2 versions of
> > > DPDK libs. So the existing apps continue to link with the previous ABI and
> > > have the possibility of migrating to the new one.
> > > Another advantage of this approach is that we don't have to wait 1 release
> > > to integrate the changes.
> > > The last advantage is to benefit early of these changes with static libraries.
> >
> > Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
> > Implementing an ABI preview option like this implies the notion that, after a
> > release, you have to remove all the ifdefs that you inserted to create the new
> > ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
> > large, and is predicated on the centralization of work effort (that is to say
> > you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
> > from the build' patch every release.
>
> It won't be so huge if we reserve the NEXT_ABI solution to changes which cannot
> have easy backward compatibility with the compat macros you introduced.
> I feel I can do the job of removing the ifdefs NEXT_ABI after each release.
> At the same time, the deprecated API, using the compat macros, will be removed.
>
I think that is something you can't really predict, as its not an issue of how
stringent we are with its use, but rather a function of how much change
developers want in a given release. That is to say, if you only reserve it for
the most important/urgently needed changes, thats fine, but if you have a
release in which 50 developers want to make urgent and important changes that
breaks ABI, you still have quite a job on your hands to back out the config
changes.
Not to mention the fact that backing those changes out is a manual process.
> > What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
> > the sort that Thomas Herbert proposed a few weeks ago).
>
> This tree was created after Thomas' request:
> http://dpdk.org/browse/next/dpdk-next/
>
Awesome, Though I'm not sure thats entirely the right place either. IIRC that
location was intended to be an early integration site that took unreviewed
patches. I think this really calls for a branch from the mainline tree that
exclusively accepts reviewed ABI changing patches, that can then be merged after
the next release
> > Patches that aren't ABI stable can be put on the next-branch/tree in thier
> > final format. You can delcare the branch unstable (thereby reserving your
> > right to rebase it). People can use that to preview the next ABI version
> > (complete with the update LIBABIVER bump), and when you release dpdk-X,
> > the new ABI for dpdk-X+1 is achieved by simply merging.
>
> Having this tree living would be a nice improvement but it won't provide any
> stable (and enough validated) releases to rely on.
>
I'm not sure I follow you entirely here. If the goal is to find a place to
accept patches that are ABI altering ahead of the main release, why do you need
to provide stable/validated releases? Just base it off the HEAD of the git tree
during the DPDK release X merge window, any testing done in the base branch
should roughly apply, save for functional changes made by the ABI patches you
add in on the branch.
Neil
>
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 13:02 9% ` Neil Horman
@ 2015-06-19 13:16 4% ` Thomas Monjalon
2015-06-19 15:27 9% ` Neil Horman
2015-06-19 16:13 9% ` Thomas F Herbert
0 siblings, 2 replies; 200+ results
From: Thomas Monjalon @ 2015-06-19 13:16 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-19 09:02, Neil Horman:
> On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
> > 2015-06-19 06:26, Neil Horman:
> > > On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> > > > For the 2.1 release, I think we should agree to make patches that change
> > > > the ABI controllable via a compile-time option. I like Olivier's proposal
> > > > on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
> > > > changes instead of a separate option per patch set (see
> > > > http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
> > > > should rework the affected patch sets to use that approach for 2.1.
> > >
> > > This is a bad idea. Making ABI dependent on compile time options isn't a
> > > maintainable solution. It breaks the notion of how LIBABIVER is supposed to
> > > work (that is to say you make it impossible to really tell what ABI version you
> > > are building).
> >
> > The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
> > So one ABI version number refers always to the same ABI.
> >
> > > If you have two compile time options that modify the ABI, you
> > > have to burn through 4 possible LIBABIVER version values to accomodate all
> > > possible combinations, and then you need to remember that when you make them
> > > statically applicable.
> >
> > The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
> >
> > Your intent when introducing ABI policy was to allow smooth porting of
> > applications from a DPDK version to another. Right?
> > The adopted solution was to provide backward compatibility during 1 release.
> > But there are cases where it's not possible. So the policy was to notice
> > the future change and wait one release cycle to break the ABI (failing
> > compatibility goals).
> > The compile-time option may provide an alternative DPDK packaging when the
> > ABI backward compatibility cannot be provided (case of mbuf changes).
> > In such case, it's still possible to upgrade DPDK by providing 2 versions of
> > DPDK libs. So the existing apps continue to link with the previous ABI and
> > have the possibility of migrating to the new one.
> > Another advantage of this approach is that we don't have to wait 1 release
> > to integrate the changes.
> > The last advantage is to benefit early of these changes with static libraries.
>
> Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
> Implementing an ABI preview option like this implies the notion that, after a
> release, you have to remove all the ifdefs that you inserted to create the new
> ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
> large, and is predicated on the centralization of work effort (that is to say
> you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
> from the build' patch every release.
It won't be so huge if we reserve the NEXT_ABI solution to changes which cannot
have easy backward compatibility with the compat macros you introduced.
I feel I can do the job of removing the ifdefs NEXT_ABI after each release.
At the same time, the deprecated API, using the compat macros, will be removed.
> What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
> the sort that Thomas Herbert proposed a few weeks ago).
This tree was created after Thomas' request:
http://dpdk.org/browse/next/dpdk-next/
> Patches that aren't ABI stable can be put on the next-branch/tree in thier
> final format. You can delcare the branch unstable (thereby reserving your
> right to rebase it). People can use that to preview the next ABI version
> (complete with the update LIBABIVER bump), and when you release dpdk-X,
> the new ABI for dpdk-X+1 is achieved by simply merging.
Having this tree living would be a nice improvement but it won't provide any
stable (and enough validated) releases to rely on.
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 12:32 9% ` Thomas Monjalon
@ 2015-06-19 13:02 9% ` Neil Horman
2015-06-19 13:16 4% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Neil Horman @ 2015-06-19 13:02 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
On Fri, Jun 19, 2015 at 02:32:33PM +0200, Thomas Monjalon wrote:
> 2015-06-19 06:26, Neil Horman:
> > On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> > > For the 2.1 release, I think we should agree to make patches that change
> > > the ABI controllable via a compile-time option. I like Olivier's proposal
> > > on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
> > > changes instead of a separate option per patch set (see
> > > http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
> > > should rework the affected patch sets to use that approach for 2.1.
> >
> > This is a bad idea. Making ABI dependent on compile time options isn't a
> > maintainable solution. It breaks the notion of how LIBABIVER is supposed to
> > work (that is to say you make it impossible to really tell what ABI version you
> > are building).
>
> The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
> So one ABI version number refers always to the same ABI.
>
> > If you have two compile time options that modify the ABI, you
> > have to burn through 4 possible LIBABIVER version values to accomodate all
> > possible combinations, and then you need to remember that when you make them
> > statically applicable.
>
> The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
>
> Your intent when introducing ABI policy was to allow smooth porting of
> applications from a DPDK version to another. Right?
> The adopted solution was to provide backward compatibility during 1 release.
> But there are cases where it's not possible. So the policy was to notice
> the future change and wait one release cycle to break the ABI (failing
> compatibility goals).
> The compile-time option may provide an alternative DPDK packaging when the
> ABI backward compatibility cannot be provided (case of mbuf changes).
> In such case, it's still possible to upgrade DPDK by providing 2 versions of
> DPDK libs. So the existing apps continue to link with the previous ABI and
> have the possibility of migrating to the new one.
> Another advantage of this approach is that we don't have to wait 1 release
> to integrate the changes.
> The last advantage is to benefit early of these changes with static libraries.
>
Hm, ok, thats a bit more reasonable, but it still seems shaky to me.
Implementing an ABI preview option like this implies the notion that, after a
release, you have to remove all the ifdefs that you inserted to create the new
ABI. That seems like an easy task, but it becomes a pain when the ABI delta is
large, and is predicated on the centralization of work effort (that is to say
you need to identify someone to submit the 'remove the NEXT_ABI config ifdefs
from the build' patch every release.
What might be better would be a dpdk-next branch (or even a dpdk-next tree, of
the sort that Thomas Herbert proposed a few weeks ago). Patches that aren't ABI
stable can be put on the next-branch/tree in thier final format. You can
delcare the branch unstable (thereby reserving your right to rebase it). People
can use that to preview the next ABI version (complete with the update LIBABIVER
bump), and when you release dpdk-X, the new ABI for dpdk-X+1 is achieved by
simply merging.
Neil
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-19 10:26 9% ` Neil Horman
@ 2015-06-19 12:32 9% ` Thomas Monjalon
2015-06-19 13:02 9% ` Neil Horman
0 siblings, 1 reply; 200+ results
From: Thomas Monjalon @ 2015-06-19 12:32 UTC (permalink / raw)
To: Neil Horman; +Cc: dev
2015-06-19 06:26, Neil Horman:
> On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> > For the 2.1 release, I think we should agree to make patches that change
> > the ABI controllable via a compile-time option. I like Olivier's proposal
> > on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these
> > changes instead of a separate option per patch set (see
> > http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we
> > should rework the affected patch sets to use that approach for 2.1.
>
> This is a bad idea. Making ABI dependent on compile time options isn't a
> maintainable solution. It breaks the notion of how LIBABIVER is supposed to
> work (that is to say you make it impossible to really tell what ABI version you
> are building).
The idea was to make LIBABIVER increment dependent of CONFIG_RTE_NEXT_ABI.
So one ABI version number refers always to the same ABI.
> If you have two compile time options that modify the ABI, you
> have to burn through 4 possible LIBABIVER version values to accomodate all
> possible combinations, and then you need to remember that when you make them
> statically applicable.
The idea is to have only 1 compile-time option: CONFIG_RTE_NEXT_ABI.
Your intent when introducing ABI policy was to allow smooth porting of
applications from a DPDK version to another. Right?
The adopted solution was to provide backward compatibility during 1 release.
But there are cases where it's not possible. So the policy was to notice
the future change and wait one release cycle to break the ABI (failing
compatibility goals).
The compile-time option may provide an alternative DPDK packaging when the
ABI backward compatibility cannot be provided (case of mbuf changes).
In such case, it's still possible to upgrade DPDK by providing 2 versions of
DPDK libs. So the existing apps continue to link with the previous ABI and
have the possibility of migrating to the new one.
Another advantage of this approach is that we don't have to wait 1 release
to integrate the changes.
The last advantage is to benefit early of these changes with static libraries.
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 11:06 4% ` Richardson, Bruce
@ 2015-06-19 11:08 7% ` Mcnamara, John
0 siblings, 0 replies; 200+ results
From: Mcnamara, John @ 2015-06-19 11:08 UTC (permalink / raw)
To: Richardson, Bruce, Neil Horman, Thomas Monjalon; +Cc: dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Richardson, Bruce
> Sent: Wednesday, June 17, 2015 12:07 PM
> To: Neil Horman; Thomas Monjalon
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-announce] important design choices -
> statistics - ABI
> Hi Neil,
>
> on my end, some suggestions:
>
> 1. the documentation on changing an API function provided in rte_compat.h
> is really good, but I don't think this is present in our documentation in
> the docs folder or on website is it (apologies if it is and I've missed
> it)? This needs to go into programmers guide or some other doc (perhaps
> the new doc that the coding style went into).
>
> 2. The documentation also needs an example of: this is how you add a new
> function and update the map file, and this is how you a) mark a function
> as deprecated and b) remove it completely. That way we could have one
> guide covering API versioning, how to add, modify and remove functions.
>
> 3. This doc should also cover how to use the API checker tool, something I
> haven't had the chance to look at yet, but should do in the near future!
> :-)
+1 on all three. We need better documentation on how to work with the ABI in DPDK. A new document in doc/guides/guidelines/ would be good.
John
^ permalink raw reply [relevance 7%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-18 16:55 8% ` O'Driscoll, Tim
2015-06-18 21:13 4% ` Vincent JARDIN
@ 2015-06-19 10:26 9% ` Neil Horman
2015-06-19 12:32 9% ` Thomas Monjalon
1 sibling, 1 reply; 200+ results
From: Neil Horman @ 2015-06-19 10:26 UTC (permalink / raw)
To: O'Driscoll, Tim; +Cc: dev
On Thu, Jun 18, 2015 at 04:55:45PM +0000, O'Driscoll, Tim wrote:
> > -----Original Message-----
> > From: announce [mailto:announce-bounces@dpdk.org] On Behalf Of Thomas
> > Monjalon
> > Sent: Wednesday, June 17, 2015 12:30 AM
> > To: announce@dpdk.org
> > Subject: [dpdk-announce] important design choices - statistics - ABI
> >
> > Hi all,
> >
>
> > During the development of the release 2.0, there was an agreement to
> > keep
> > ABI compatibility or to bring new ABI while keeping old one during one
> > release.
> > In case it's not possible to have this transition, the (exceptional)
> > break
> > should be acknowledged by several developers.
> > http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
> > There were some interesting discussions but not a lot of participants:
> > http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus
> > =8461
> >
> > During the current development cycle for the release 2.1, the ABI
> > question
> > arises many times in different threads.
> > To add the hash key size field, it is proposed to use a struct padding
> > gap:
> > http://dpdk.org/ml/archives/dev/2015-June/019386.html
> > To support the flow director for VF, there is no proposal yet:
> > http://dpdk.org/ml/archives/dev/2015-June/019343.html
> > To add the speed capability, it is proposed to break ABI in the release
> > 2.2:
> > http://dpdk.org/ml/archives/dev/2015-June/019225.html
> > To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
> > http://dpdk.org/ml/archives/dev/2015-June/019443.html
> > To add the interrupt mode, it is proposed to add a build-time option
> > CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking
> > binary:
> > http://dpdk.org/ml/archives/dev/2015-June/018947.html
> > To add the packet type, there is a proposal to add a build-time option
> > CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
> > http://dpdk.org/ml/archives/dev/2015-June/019172.html
> > We must also better document how to remove a deprecated ABI:
> > http://dpdk.org/ml/archives/dev/2015-June/019465.html
> > The ABI compatibility is a new constraint and we need to better
> > understand
> > what it means and how to proceed. Even the macros are not yet well
> > documented:
> > http://dpdk.org/ml/archives/dev/2015-June/019357.html
> >
> > Thanks for your attention and your participation in these important
> > choices.
>
> There's been some good discussion on the ABI policy in various responses to this email. I think we now need to reach a conclusion on how we're going to proceed for the 2.1 release. Then, we can have further discussion on the use of versioning or other methods for avoiding the problem in future.
>
> For the 2.1 release, I think we should agree to make patches that change the ABI controllable via a compile-time option. I like Olivier's proposal on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these changes instead of a separate option per patch set (see http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we should rework the affected patch sets to use that approach for 2.1.
>
This is a bad idea. Making ABI dependent on compile time options isn't a
maintainable solution. It breaks the notion of how LIBABIVER is supposed to
work (that is to say you make it impossible to really tell what ABI version you
are building). If you have two compile time options that modify the ABI, you
have to burn through 4 possible LIBABIVER version values to accomodate all
possible combinations, and then you need to remember that when you make them
statically applicable.
Neil
>
> Tim
>
^ permalink raw reply [relevance 9%]
* [dpdk-dev] [PATCH v7 18/18] mbuf: remove old packet type bit masks
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (16 preceding siblings ...)
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 17/18] examples/l3fwd: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
As unified packet types are used instead, those old bit masks and
the relevant macros for packet type indication need to be removed.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_mbuf/rte_mbuf.c | 4 ++++
lib/librte_mbuf/rte_mbuf.h | 4 ++++
2 files changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
* Redefined the bit masks for packet RX offload flags.
v5 changes:
* Rolled back the bit masks of RX flags, for ABI compatibility.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index f506517..4320dd4 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -251,14 +251,18 @@ const char *rte_get_rx_ol_flag_name(uint64_t mask)
/* case PKT_RX_HBUF_OVERFLOW: return "PKT_RX_HBUF_OVERFLOW"; */
/* case PKT_RX_RECIP_ERR: return "PKT_RX_RECIP_ERR"; */
/* case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; */
+#ifndef RTE_NEXT_ABI
case PKT_RX_IPV4_HDR: return "PKT_RX_IPV4_HDR";
case PKT_RX_IPV4_HDR_EXT: return "PKT_RX_IPV4_HDR_EXT";
case PKT_RX_IPV6_HDR: return "PKT_RX_IPV6_HDR";
case PKT_RX_IPV6_HDR_EXT: return "PKT_RX_IPV6_HDR_EXT";
+#endif /* RTE_NEXT_ABI */
case PKT_RX_IEEE1588_PTP: return "PKT_RX_IEEE1588_PTP";
case PKT_RX_IEEE1588_TMST: return "PKT_RX_IEEE1588_TMST";
+#ifndef RTE_NEXT_ABI
case PKT_RX_TUNNEL_IPV4_HDR: return "PKT_RX_TUNNEL_IPV4_HDR";
case PKT_RX_TUNNEL_IPV6_HDR: return "PKT_RX_TUNNEL_IPV6_HDR";
+#endif /* RTE_NEXT_ABI */
default: return NULL;
}
}
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 5e7cc26..9f32edf 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -91,14 +91,18 @@ extern "C" {
#define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer overflow. */
#define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing error. */
#define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */
+#ifndef RTE_NEXT_ABI
#define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 header. */
#define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with extended IPv4 header. */
#define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 header. */
#define PKT_RX_IPV6_HDR_EXT (1ULL << 8) /**< RX packet with extended IPv6 header. */
+#endif /* RTE_NEXT_ABI */
#define PKT_RX_IEEE1588_PTP (1ULL << 9) /**< RX IEEE1588 L2 Ethernet PT Packet. */
#define PKT_RX_IEEE1588_TMST (1ULL << 10) /**< RX IEEE1588 L2/L4 timestamped packet.*/
+#ifndef RTE_NEXT_ABI
#define PKT_RX_TUNNEL_IPV4_HDR (1ULL << 11) /**< RX tunnel packet with IPv4 header.*/
#define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet with IPv6 header. */
+#endif /* RTE_NEXT_ABI */
#define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR match. */
#define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported if FDIR match. */
#define PKT_RX_QINQ_PKT (1ULL << 15) /**< RX packet with double VLAN stripped. */
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 17/18] examples/l3fwd: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (15 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 16/18] examples/l3fwd-power: " Helin Zhang
@ 2015-06-19 8:14 3% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 18/18] mbuf: remove old packet type bit masks Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd/main.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 120 insertions(+), 3 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v3 changes:
* Minor bug fixes and enhancements.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 7e4bbfd..eff9580 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -948,7 +948,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
/* Handle IPv4 headers.*/
ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(m, unsigned char *) +
sizeof(struct ether_hdr));
@@ -979,8 +983,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
} else {
+#endif
/* Handle IPv6 headers.*/
struct ipv6_hdr *ipv6_hdr;
@@ -999,8 +1006,13 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
+#ifdef RTE_NEXT_ABI
+ } else
+ /* Free the mbuf that contains non-IPV4/IPV6 packet */
+ rte_pktmbuf_free(m);
+#else
}
-
+#endif
}
#ifdef DO_RFC_1812_CHECKS
@@ -1024,12 +1036,19 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qcon
* to BAD_PORT value.
*/
static inline __attribute__((always_inline)) void
+#ifdef RTE_NEXT_ABI
+rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype)
+#else
rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t flags)
+#endif
{
uint8_t ihl;
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(ptype)) {
+#else
if ((flags & PKT_RX_IPV4_HDR) != 0) {
-
+#endif
ihl = ipv4_hdr->version_ihl - IPV4_MIN_VER_IHL;
ipv4_hdr->time_to_live--;
@@ -1059,11 +1078,19 @@ get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
struct ipv6_hdr *ipv6_hdr;
struct ether_hdr *eth_hdr;
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
if (pkt->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
if (rte_lpm_lookup(qconf->ipv4_lookup_struct, dst_ipv4,
&next_hop) != 0)
next_hop = portid;
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (pkt->ol_flags & PKT_RX_IPV6_HDR) {
+#endif
eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1);
if (rte_lpm6_lookup(qconf->ipv6_lookup_struct,
@@ -1097,12 +1124,52 @@ process_packet(struct lcore_conf *qconf, struct rte_mbuf *pkt,
ve = val_eth[dp];
dst_port[0] = dp;
+#ifdef RTE_NEXT_ABI
+ rfc1812_process(ipv4_hdr, dst_port, pkt->packet_type);
+#else
rfc1812_process(ipv4_hdr, dst_port, pkt->ol_flags);
+#endif
te = _mm_blend_epi16(te, ve, MASK_ETH);
_mm_store_si128((__m128i *)eth_hdr, te);
}
+#ifdef RTE_NEXT_ABI
+/*
+ * Read packet_type and destination IPV4 addresses from 4 mbufs.
+ */
+static inline void
+processx4_step1(struct rte_mbuf *pkt[FWDSTEP],
+ __m128i *dip,
+ uint32_t *ipv4_flag)
+{
+ struct ipv4_hdr *ipv4_hdr;
+ struct ether_hdr *eth_hdr;
+ uint32_t x0, x1, x2, x3;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[0], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x0 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] = pkt[0]->packet_type & RTE_PTYPE_L3_IPV4;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[1], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x1 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[1]->packet_type;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[2], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x2 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[2]->packet_type;
+
+ eth_hdr = rte_pktmbuf_mtod(pkt[3], struct ether_hdr *);
+ ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ x3 = ipv4_hdr->dst_addr;
+ ipv4_flag[0] &= pkt[3]->packet_type;
+
+ dip[0] = _mm_set_epi32(x3, x2, x1, x0);
+}
+#else /* RTE_NEXT_ABI */
/*
* Read ol_flags and destination IPV4 addresses from 4 mbufs.
*/
@@ -1135,14 +1202,24 @@ processx4_step1(struct rte_mbuf *pkt[FWDSTEP], __m128i *dip, uint32_t *flag)
dip[0] = _mm_set_epi32(x3, x2, x1, x0);
}
+#endif /* RTE_NEXT_ABI */
/*
* Lookup into LPM for destination port.
* If lookup fails, use incoming port (portid) as destination port.
*/
static inline void
+#ifdef RTE_NEXT_ABI
+processx4_step2(const struct lcore_conf *qconf,
+ __m128i dip,
+ uint32_t ipv4_flag,
+ uint8_t portid,
+ struct rte_mbuf *pkt[FWDSTEP],
+ uint16_t dprt[FWDSTEP])
+#else
processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag,
uint8_t portid, struct rte_mbuf *pkt[FWDSTEP], uint16_t dprt[FWDSTEP])
+#endif /* RTE_NEXT_ABI */
{
rte_xmm_t dst;
const __m128i bswap_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11,
@@ -1152,7 +1229,11 @@ processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag,
dip = _mm_shuffle_epi8(dip, bswap_mask);
/* if all 4 packets are IPV4. */
+#ifdef RTE_NEXT_ABI
+ if (likely(ipv4_flag)) {
+#else
if (likely(flag != 0)) {
+#endif
rte_lpm_lookupx4(qconf->ipv4_lookup_struct, dip, dprt, portid);
} else {
dst.x = dip;
@@ -1202,6 +1283,16 @@ processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
_mm_store_si128(p[2], te[2]);
_mm_store_si128(p[3], te[3]);
+#ifdef RTE_NEXT_ABI
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1),
+ &dst_port[0], pkt[0]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1),
+ &dst_port[1], pkt[1]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[2] + 1),
+ &dst_port[2], pkt[2]->packet_type);
+ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1),
+ &dst_port[3], pkt[3]->packet_type);
+#else /* RTE_NEXT_ABI */
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1),
&dst_port[0], pkt[0]->ol_flags);
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1),
@@ -1210,6 +1301,7 @@ processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP])
&dst_port[2], pkt[2]->ol_flags);
rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1),
&dst_port[3], pkt[3]->ol_flags);
+#endif /* RTE_NEXT_ABI */
}
/*
@@ -1396,7 +1488,11 @@ main_loop(__attribute__((unused)) void *dummy)
uint16_t *lp;
uint16_t dst_port[MAX_PKT_BURST];
__m128i dip[MAX_PKT_BURST / FWDSTEP];
+#ifdef RTE_NEXT_ABI
+ uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP];
+#else
uint32_t flag[MAX_PKT_BURST / FWDSTEP];
+#endif
uint16_t pnum[MAX_PKT_BURST + 1];
#endif
@@ -1466,6 +1562,18 @@ main_loop(__attribute__((unused)) void *dummy)
*/
int32_t n = RTE_ALIGN_FLOOR(nb_rx, 4);
for (j = 0; j < n ; j+=4) {
+#ifdef RTE_NEXT_ABI
+ uint32_t pkt_type =
+ pkts_burst[j]->packet_type &
+ pkts_burst[j+1]->packet_type &
+ pkts_burst[j+2]->packet_type &
+ pkts_burst[j+3]->packet_type;
+ if (pkt_type & RTE_PTYPE_L3_IPV4) {
+ simple_ipv4_fwd_4pkts(
+ &pkts_burst[j], portid, qconf);
+ } else if (pkt_type &
+ RTE_PTYPE_L3_IPV6) {
+#else /* RTE_NEXT_ABI */
uint32_t ol_flag = pkts_burst[j]->ol_flags
& pkts_burst[j+1]->ol_flags
& pkts_burst[j+2]->ol_flags
@@ -1474,6 +1582,7 @@ main_loop(__attribute__((unused)) void *dummy)
simple_ipv4_fwd_4pkts(&pkts_burst[j],
portid, qconf);
} else if (ol_flag & PKT_RX_IPV6_HDR) {
+#endif /* RTE_NEXT_ABI */
simple_ipv6_fwd_4pkts(&pkts_burst[j],
portid, qconf);
} else {
@@ -1498,13 +1607,21 @@ main_loop(__attribute__((unused)) void *dummy)
for (j = 0; j != k; j += FWDSTEP) {
processx4_step1(&pkts_burst[j],
&dip[j / FWDSTEP],
+#ifdef RTE_NEXT_ABI
+ &ipv4_flag[j / FWDSTEP]);
+#else
&flag[j / FWDSTEP]);
+#endif
}
k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP);
for (j = 0; j != k; j += FWDSTEP) {
processx4_step2(qconf, dip[j / FWDSTEP],
+#ifdef RTE_NEXT_ABI
+ ipv4_flag[j / FWDSTEP], portid,
+#else
flag[j / FWDSTEP], portid,
+#endif
&pkts_burst[j], &dst_port[j]);
}
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 16/18] examples/l3fwd-power: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (14 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 15/18] examples/l3fwd-acl: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 17/18] examples/l3fwd: " Helin Zhang
` (2 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd-power/main.c | 8 ++++++++
1 file changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index 6057059..705188f 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -635,7 +635,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
/* Handle IPv4 headers.*/
ipv4_hdr =
(struct ipv4_hdr *)(rte_pktmbuf_mtod(m, unsigned char*)
@@ -670,8 +674,12 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid,
ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr);
send_single_packet(m, dst_port);
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
}
else {
+#endif
/* Handle IPv6 headers.*/
#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
struct ipv6_hdr *ipv6_hdr;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 15/18] examples/l3fwd-acl: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (13 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 14/18] examples/ip_reassembly: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 16/18] examples/l3fwd-power: " Helin Zhang
` (3 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/l3fwd-acl/main.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c
index a5d4f25..78b6df2 100644
--- a/examples/l3fwd-acl/main.c
+++ b/examples/l3fwd-acl/main.c
@@ -645,10 +645,13 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
struct ipv4_hdr *ipv4_hdr;
struct rte_mbuf *pkt = pkts_in[index];
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR);
if (type == PKT_RX_IPV4_HDR) {
-
+#endif
ipv4_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(pkt,
unsigned char *) + sizeof(struct ether_hdr));
@@ -667,9 +670,11 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
/* Not a valid IPv4 packet */
rte_pktmbuf_free(pkt);
}
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (type == PKT_RX_IPV6_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
acl->m_ipv6[(acl->num_ipv6)++] = pkt;
@@ -687,17 +692,22 @@ prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
{
struct rte_mbuf *pkt = pkts_in[index];
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
+#else
int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR);
if (type == PKT_RX_IPV4_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
acl->m_ipv4[(acl->num_ipv4)++] = pkt;
-
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
+#else
} else if (type == PKT_RX_IPV6_HDR) {
-
+#endif
/* Fill acl structure */
acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
acl->m_ipv6[(acl->num_ipv6)++] = pkt;
@@ -745,10 +755,17 @@ send_one_packet(struct rte_mbuf *m, uint32_t res)
/* in the ACL list, drop it */
#ifdef L3FWDACL_DEBUG
if ((res & ACL_DENY_SIGNATURE) != 0) {
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type))
+ dump_acl4_rule(m, res);
+ else if (RTE_ETH_IS_IPV6_HDR(m->packet_type))
+ dump_acl6_rule(m, res);
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR)
dump_acl4_rule(m, res);
else
dump_acl6_rule(m, res);
+#endif /* RTE_NEXT_ABI */
}
#endif
rte_pktmbuf_free(m);
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 14/18] examples/ip_reassembly: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (12 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 15/18] examples/l3fwd-acl: " Helin Zhang
` (4 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/ip_reassembly/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c
index 9ecb6f9..f1c47ad 100644
--- a/examples/ip_reassembly/main.c
+++ b/examples/ip_reassembly/main.c
@@ -356,7 +356,11 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue,
dst_port = portid;
/* if packet is IPv4 */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & (PKT_RX_IPV4_HDR)) {
+#endif
struct ipv4_hdr *ip_hdr;
uint32_t ip_dst;
@@ -396,9 +400,14 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue,
}
eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4);
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ /* if packet is IPv6 */
+#else
}
/* if packet is IPv6 */
else if (m->ol_flags & (PKT_RX_IPV6_HDR | PKT_RX_IPV6_HDR_EXT)) {
+#endif
struct ipv6_extension_fragment *frag_hdr;
struct ipv6_hdr *ip_hdr;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (11 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 12/18] app/test: Remove useless code Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 14/18] examples/ip_reassembly: " Helin Zhang
` (5 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
examples/ip_fragmentation/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 0922ba6..b71d05f 100644
--- a/examples/ip_fragmentation/main.c
+++ b/examples/ip_fragmentation/main.c
@@ -283,7 +283,11 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
len = qconf->tx_mbufs[port_out].len;
/* if this is an IPv4 packet */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
struct ipv4_hdr *ip_hdr;
uint32_t ip_dst;
/* Read the lookup key (i.e. ip_dst) from the input packet */
@@ -317,9 +321,14 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
if (unlikely (len2 < 0))
return;
}
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ /* if this is an IPv6 packet */
+#else
}
/* if this is an IPv6 packet */
else if (m->ol_flags & PKT_RX_IPV6_HDR) {
+#endif
struct ipv6_hdr *ip_hdr;
ipv6 = 1;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 12/18] app/test: Remove useless code
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (10 preceding siblings ...)
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 11/18] app/testpmd: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
` (6 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
Severl useless code lines are added accidently, which blocks packet
type unification. They should be deleted at all.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
app/test/packet_burst_generator.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
v4 changes:
* Removed several useless code lines which block packet type unification.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test/packet_burst_generator.c b/app/test/packet_burst_generator.c
index b46eed7..61e6340 100644
--- a/app/test/packet_burst_generator.c
+++ b/app/test/packet_burst_generator.c
@@ -272,19 +272,21 @@ nomore_mbuf:
if (ipv4) {
pkt->vlan_tci = ETHER_TYPE_IPv4;
pkt->l3_len = sizeof(struct ipv4_hdr);
-
+#ifndef RTE_NEXT_ABI
if (vlan_enabled)
pkt->ol_flags = PKT_RX_IPV4_HDR | PKT_RX_VLAN_PKT;
else
pkt->ol_flags = PKT_RX_IPV4_HDR;
+#endif
} else {
pkt->vlan_tci = ETHER_TYPE_IPv6;
pkt->l3_len = sizeof(struct ipv6_hdr);
-
+#ifndef RTE_NEXT_ABI
if (vlan_enabled)
pkt->ol_flags = PKT_RX_IPV6_HDR | PKT_RX_VLAN_PKT;
else
pkt->ol_flags = PKT_RX_IPV6_HDR;
+#endif
}
pkts_burst[nb_pkt] = pkt;
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 11/18] app/testpmd: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (9 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 10/18] app/test-pipeline: " Helin Zhang
@ 2015-06-19 8:14 3% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 12/18] app/test: Remove useless code Helin Zhang
` (7 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Jijiang Liu <jijiang.liu@intel.com>
---
app/test-pmd/csumonly.c | 14 ++++
app/test-pmd/rxonly.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 197 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v4 changes:
* Added printing logs of packet types of each received packet in rxonly mode.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
index 950ea82..fab9600 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -202,8 +202,14 @@ parse_ethernet(struct ether_hdr *eth_hdr, struct testpmd_offload_info *info)
/* Parse a vxlan header */
static void
+#ifdef RTE_NEXT_ABI
+parse_vxlan(struct udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info,
+ uint32_t pkt_type)
+#else
parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info,
uint64_t mbuf_olflags)
+#endif
{
struct ether_hdr *eth_hdr;
@@ -211,8 +217,12 @@ parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info,
* (rfc7348) or that the rx offload flag is set (i40e only
* currently) */
if (udp_hdr->dst_port != _htons(4789) &&
+#ifdef RTE_NEXT_ABI
+ RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0)
+#else
(mbuf_olflags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR)) == 0)
+#endif
return;
info->is_tunnel = 1;
@@ -549,7 +559,11 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)
struct udp_hdr *udp_hdr;
udp_hdr = (struct udp_hdr *)((char *)l3_hdr +
info.l3_len);
+#ifdef RTE_NEXT_ABI
+ parse_vxlan(udp_hdr, &info, m->packet_type);
+#else
parse_vxlan(udp_hdr, &info, m->ol_flags);
+#endif
} else if (info.l4_proto == IPPROTO_GRE) {
struct simple_gre_hdr *gre_hdr;
gre_hdr = (struct simple_gre_hdr *)
diff --git a/app/test-pmd/rxonly.c b/app/test-pmd/rxonly.c
index f6a2f84..5a30347 100644
--- a/app/test-pmd/rxonly.c
+++ b/app/test-pmd/rxonly.c
@@ -91,7 +91,11 @@ pkt_burst_receive(struct fwd_stream *fs)
uint64_t ol_flags;
uint16_t nb_rx;
uint16_t i, packet_type;
+#ifdef RTE_NEXT_ABI
+ uint16_t is_encapsulation;
+#else
uint64_t is_encapsulation;
+#endif
#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
uint64_t start_tsc;
@@ -135,8 +139,12 @@ pkt_burst_receive(struct fwd_stream *fs)
ol_flags = mb->ol_flags;
packet_type = mb->packet_type;
+#ifdef RTE_NEXT_ABI
+ is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
+#else
is_encapsulation = ol_flags & (PKT_RX_TUNNEL_IPV4_HDR |
PKT_RX_TUNNEL_IPV6_HDR);
+#endif
print_ether_addr(" src=", ð_hdr->s_addr);
print_ether_addr(" - dst=", ð_hdr->d_addr);
@@ -163,6 +171,177 @@ pkt_burst_receive(struct fwd_stream *fs)
if (ol_flags & PKT_RX_QINQ_PKT)
printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
mb->vlan_tci, mb->vlan_tci_outer);
+#ifdef RTE_NEXT_ABI
+ if (mb->packet_type) {
+ uint32_t ptype;
+
+ /* (outer) L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L2_MAC:
+ printf(" - (outer) L2 type: MAC");
+ break;
+ case RTE_PTYPE_L2_MAC_TIMESYNC:
+ printf(" - (outer) L2 type: MAC Timesync");
+ break;
+ case RTE_PTYPE_L2_ARP:
+ printf(" - (outer) L2 type: ARP");
+ break;
+ case RTE_PTYPE_L2_LLDP:
+ printf(" - (outer) L2 type: LLDP");
+ break;
+ default:
+ printf(" - (outer) L2 type: Unknown");
+ break;
+ }
+
+ /* (outer) L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L3_IPV4:
+ printf(" - (outer) L3 type: IPV4");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT:
+ printf(" - (outer) L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6:
+ printf(" - (outer) L3 type: IPV6");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT:
+ printf(" - (outer) L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV6_EXT_UNKNOWN");
+ break;
+ default:
+ printf(" - (outer) L3 type: Unknown");
+ break;
+ }
+
+ /* (outer) L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L4_TCP:
+ printf(" - (outer) L4 type: TCP");
+ break;
+ case RTE_PTYPE_L4_UDP:
+ printf(" - (outer) L4 type: UDP");
+ break;
+ case RTE_PTYPE_L4_FRAG:
+ printf(" - (outer) L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_L4_SCTP:
+ printf(" - (outer) L4 type: SCTP");
+ break;
+ case RTE_PTYPE_L4_ICMP:
+ printf(" - (outer) L4 type: ICMP");
+ break;
+ case RTE_PTYPE_L4_NONFRAG:
+ printf(" - (outer) L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - (outer) L4 type: Unknown");
+ break;
+ }
+
+ /* packet tunnel type */
+ ptype = mb->packet_type & RTE_PTYPE_TUNNEL_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_TUNNEL_IP:
+ printf(" - Tunnel type: IP");
+ break;
+ case RTE_PTYPE_TUNNEL_GRE:
+ printf(" - Tunnel type: GRE");
+ break;
+ case RTE_PTYPE_TUNNEL_VXLAN:
+ printf(" - Tunnel type: VXLAN");
+ break;
+ case RTE_PTYPE_TUNNEL_NVGRE:
+ printf(" - Tunnel type: NVGRE");
+ break;
+ case RTE_PTYPE_TUNNEL_GENEVE:
+ printf(" - Tunnel type: GENEVE");
+ break;
+ case RTE_PTYPE_TUNNEL_GRENAT:
+ printf(" - Tunnel type: GRENAT");
+ break;
+ default:
+ printf(" - Tunnel type: Unkown");
+ break;
+ }
+
+ /* inner L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L2_MAC:
+ printf(" - Inner L2 type: MAC");
+ break;
+ case RTE_PTYPE_INNER_L2_MAC_VLAN:
+ printf(" - Inner L2 type: MAC_VLAN");
+ break;
+ default:
+ printf(" - Inner L2 type: Unknown");
+ break;
+ }
+
+ /* inner L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_INNER_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L3_IPV4:
+ printf(" - Inner L3 type: IPV4");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT:
+ printf(" - Inner L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6:
+ printf(" - Inner L3 type: IPV6");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN:
+ printf(" - Inner L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT:
+ printf(" - Inner L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN:
+ printf(" - Inner L3 type: IPV6_EXT_UNKOWN");
+ break;
+ default:
+ printf(" - Inner L3 type: Unkown");
+ break;
+ }
+
+ /* inner L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L4_TCP:
+ printf(" - Inner L4 type: TCP");
+ break;
+ case RTE_PTYPE_INNER_L4_UDP:
+ printf(" - Inner L4 type: UDP");
+ break;
+ case RTE_PTYPE_INNER_L4_FRAG:
+ printf(" - Inner L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_INNER_L4_SCTP:
+ printf(" - Inner L4 type: SCTP");
+ break;
+ case RTE_PTYPE_INNER_L4_ICMP:
+ printf(" - Inner L4 type: ICMP");
+ break;
+ case RTE_PTYPE_INNER_L4_NONFRAG:
+ printf(" - Inner L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - Inner L4 type: Unknown");
+ break;
+ }
+ printf("\n");
+ } else
+ printf("Unknown packet type\n");
+#endif /* RTE_NEXT_ABI */
if (is_encapsulation) {
struct ipv4_hdr *ipv4_hdr;
struct ipv6_hdr *ipv6_hdr;
@@ -176,7 +355,11 @@ pkt_burst_receive(struct fwd_stream *fs)
l2_len = sizeof(struct ether_hdr);
/* Do not support ipv4 option field */
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(packet_type)) {
+#else
if (ol_flags & PKT_RX_TUNNEL_IPV4_HDR) {
+#endif
l3_len = sizeof(struct ipv4_hdr);
ipv4_hdr = (struct ipv4_hdr *) (rte_pktmbuf_mtod(mb,
unsigned char *) + l2_len);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 10/18] app/test-pipeline: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (8 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 09/18] fm10k: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 11/18] app/testpmd: " Helin Zhang
` (8 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
app/test-pipeline/pipeline_hash.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/app/test-pipeline/pipeline_hash.c b/app/test-pipeline/pipeline_hash.c
index 4598ad4..aa3f9e5 100644
--- a/app/test-pipeline/pipeline_hash.c
+++ b/app/test-pipeline/pipeline_hash.c
@@ -459,20 +459,33 @@ app_main_loop_rx_metadata(void) {
signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0);
key = RTE_MBUF_METADATA_UINT8_PTR(m, 32);
+#ifdef RTE_NEXT_ABI
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+#else
if (m->ol_flags & PKT_RX_IPV4_HDR) {
+#endif
ip_hdr = (struct ipv4_hdr *)
&m_data[sizeof(struct ether_hdr)];
ip_dst = ip_hdr->dst_addr;
k32 = (uint32_t *) key;
k32[0] = ip_dst & 0xFFFFFF00;
+#ifdef RTE_NEXT_ABI
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+#else
} else {
+#endif
ipv6_hdr = (struct ipv6_hdr *)
&m_data[sizeof(struct ether_hdr)];
ipv6_dst = ipv6_hdr->dst_addr;
memcpy(key, ipv6_dst, 16);
+#ifdef RTE_NEXT_ABI
+ } else
+ continue;
+#else
}
+#endif
*signature = test_hash(key, 0, 0);
}
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 09/18] fm10k: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (7 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 08/18] vmxnet3: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 10/18] app/test-pipeline: " Helin Zhang
` (9 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/fm10k/fm10k_rxtx.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
v4 changes:
* Supported unified packet type of fm10k from v4.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/fm10k/fm10k_rxtx.c b/drivers/net/fm10k/fm10k_rxtx.c
index 56df6cd..45005c2 100644
--- a/drivers/net/fm10k/fm10k_rxtx.c
+++ b/drivers/net/fm10k/fm10k_rxtx.c
@@ -68,12 +68,37 @@ static inline void dump_rxd(union fm10k_rx_desc *rxd)
static inline void
rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d)
{
+#ifdef RTE_NEXT_ABI
+ static const uint32_t
+ ptype_table[FM10K_RXD_PKTTYPE_MASK >> FM10K_RXD_PKTTYPE_SHIFT]
+ __rte_cache_aligned = {
+ [FM10K_PKTTYPE_OTHER] = RTE_PTYPE_L2_MAC,
+ [FM10K_PKTTYPE_IPV4] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4,
+ [FM10K_PKTTYPE_IPV4_EX] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [FM10K_PKTTYPE_IPV6] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6,
+ [FM10K_PKTTYPE_IPV6_EX] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ };
+
+ m->packet_type = ptype_table[(d->w.pkt_info & FM10K_RXD_PKTTYPE_MASK)
+ >> FM10K_RXD_PKTTYPE_SHIFT];
+#else /* RTE_NEXT_ABI */
uint16_t ptype;
static const uint16_t pt_lut[] = { 0,
PKT_RX_IPV4_HDR, PKT_RX_IPV4_HDR_EXT,
PKT_RX_IPV6_HDR, PKT_RX_IPV6_HDR_EXT,
0, 0, 0
};
+#endif /* RTE_NEXT_ABI */
if (d->w.pkt_info & FM10K_RXD_RSSTYPE_MASK)
m->ol_flags |= PKT_RX_RSS_HASH;
@@ -97,9 +122,11 @@ rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d)
if (unlikely(d->d.staterr & FM10K_RXD_STATUS_RXE))
m->ol_flags |= PKT_RX_RECIP_ERR;
+#ifndef RTE_NEXT_ABI
ptype = (d->d.data & FM10K_RXD_PKTTYPE_MASK_L3) >>
FM10K_RXD_PKTTYPE_SHIFT;
m->ol_flags |= pt_lut[(uint8_t)ptype];
+#endif
}
uint16_t
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 08/18] vmxnet3: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (6 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 07/18] enic: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 09/18] fm10k: " Helin Zhang
` (10 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 ++++++++
1 file changed, 8 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c b/drivers/net/vmxnet3/vmxnet3_rxtx.c
index a1eac45..25ae2f6 100644
--- a/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -649,9 +649,17 @@ vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
struct ipv4_hdr *ip = (struct ipv4_hdr *)(eth + 1);
if (((ip->version_ihl & 0xf) << 2) > (int)sizeof(struct ipv4_hdr))
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = RTE_PTYPE_L3_IPV4_EXT;
+#else
rxm->ol_flags |= PKT_RX_IPV4_HDR_EXT;
+#endif
else
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rxm->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!rcd->cnc) {
if (!rcd->ipc)
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 06/18] i40e: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (4 preceding siblings ...)
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 05/18] ixgbe: " Helin Zhang
@ 2015-06-19 8:14 3% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 07/18] enic: " Helin Zhang
` (12 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/i40e/i40e_rxtx.c | 528 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 528 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index b2e1d6d..b951da0 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -176,6 +176,514 @@ i40e_rxd_error_to_pkt_flags(uint64_t qword)
return flags;
}
+#ifdef RTE_NEXT_ABI
+/* For each value it means, datasheet of hardware can tell more details */
+static inline uint32_t
+i40e_rxd_pkt_type_mapping(uint8_t ptype)
+{
+ static const uint32_t ptype_table[UINT8_MAX] __rte_cache_aligned = {
+ /* L2 types */
+ /* [0] reserved */
+ [1] = RTE_PTYPE_L2_MAC,
+ [2] = RTE_PTYPE_L2_MAC_TIMESYNC,
+ /* [3] - [5] reserved */
+ [6] = RTE_PTYPE_L2_LLDP,
+ /* [7] - [10] reserved */
+ [11] = RTE_PTYPE_L2_ARP,
+ /* [12] - [21] reserved */
+
+ /* Non tunneled IPv4 */
+ [22] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG,
+ [23] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG,
+ [24] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP,
+ /* [25] reserved */
+ [26] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP,
+ [27] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP,
+ [28] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP,
+
+ /* IPv4 --> IPv4 */
+ [29] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [30] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [31] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [32] reserved */
+ [33] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [34] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [35] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> IPv6 */
+ [36] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [37] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [38] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [39] reserved */
+ [40] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [41] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [42] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN */
+ [43] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> IPv4 */
+ [44] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [45] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [46] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [47] reserved */
+ [48] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [49] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [50] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> IPv6 */
+ [51] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [52] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [53] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [54] reserved */
+ [55] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [56] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [57] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC */
+ [58] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */
+ [59] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [60] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [61] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [62] reserved */
+ [63] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [64] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [65] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */
+ [66] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [67] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [68] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [69] reserved */
+ [70] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [71] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [72] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN */
+ [73] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */
+ [74] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [75] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [76] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [77] reserved */
+ [78] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [79] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [80] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */
+ [81] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [82] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [83] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [84] reserved */
+ [85] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [86] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [87] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* Non tunneled IPv6 */
+ [88] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG,
+ [89] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG,
+ [90] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP,
+ /* [91] reserved */
+ [92] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP,
+ [93] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP,
+ [94] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP,
+
+ /* IPv6 --> IPv4 */
+ [95] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [96] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [97] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [98] reserved */
+ [99] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [100] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [101] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> IPv6 */
+ [102] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [103] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [104] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [105] reserved */
+ [106] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [107] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [108] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN */
+ [109] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> IPv4 */
+ [110] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [111] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [112] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [113] reserved */
+ [114] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [115] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [116] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> IPv6 */
+ [117] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [118] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [119] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [120] reserved */
+ [121] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [122] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [123] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC */
+ [124] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */
+ [125] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [126] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [127] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [128] reserved */
+ [129] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [130] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [131] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */
+ [132] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [133] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [134] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [135] reserved */
+ [136] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [137] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [138] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN */
+ [139] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */
+ [140] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [141] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [142] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [143] reserved */
+ [144] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [145] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [146] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */
+ [147] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG,
+ [148] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ [149] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP,
+ /* [150] reserved */
+ [151] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP,
+ [152] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP,
+ [153] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_MAC_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP,
+
+ /* All others reserved */
+ };
+
+ return ptype_table[ptype];
+}
+#else /* RTE_NEXT_ABI */
/* Translate pkt types to pkt flags */
static inline uint64_t
i40e_rxd_ptype_to_pkt_flags(uint64_t qword)
@@ -443,6 +951,7 @@ i40e_rxd_ptype_to_pkt_flags(uint64_t qword)
return ip_ptype_map[ptype];
}
+#endif /* RTE_NEXT_ABI */
#define I40E_RX_DESC_EXT_STATUS_FLEXBH_MASK 0x03
#define I40E_RX_DESC_EXT_STATUS_FLEXBH_FD_ID 0x01
@@ -730,11 +1239,18 @@ i40e_rx_scan_hw_ring(struct i40e_rx_queue *rxq)
i40e_rxd_to_vlan_tci(mb, &rxdp[j]);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ mb->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
mb->packet_type = (uint16_t)((qword1 &
I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
mb->hash.rss = rte_le_to_cpu_32(\
rxdp[j].wb.qword0.hi_dword.rss);
@@ -971,9 +1487,15 @@ i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
i40e_rxd_to_vlan_tci(rxm, &rxd);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
rxm->packet_type = (uint16_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
rxm->hash.rss =
rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss);
@@ -1129,10 +1651,16 @@ i40e_recv_scattered_pkts(void *rx_queue,
i40e_rxd_to_vlan_tci(first_seg, &rxd);
pkt_flags = i40e_rxd_status_to_pkt_flags(qword1);
pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1);
+#ifdef RTE_NEXT_ABI
+ first_seg->packet_type =
+ i40e_rxd_pkt_type_mapping((uint8_t)((qword1 &
+ I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT));
+#else
pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1);
first_seg->packet_type = (uint16_t)((qword1 &
I40E_RXD_QW1_PTYPE_MASK) >>
I40E_RXD_QW1_PTYPE_SHIFT);
+#endif /* RTE_NEXT_ABI */
if (pkt_flags & PKT_RX_RSS_HASH)
rxm->hash.rss =
rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 07/18] enic: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (5 preceding siblings ...)
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 06/18] i40e: " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 08/18] vmxnet3: " Helin Zhang
` (11 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/enic/enic_main.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 15313c2..f47e96c 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -423,7 +423,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
rx_pkt->pkt_len = bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD;
@@ -432,7 +436,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
} else {
/* Header split */
if (sop && !eop) {
@@ -445,7 +453,11 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
*rx_pkt_bucket = rx_pkt;
rx_pkt->pkt_len = bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV4;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
rx_pkt->ol_flags |=
@@ -457,13 +469,22 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ rx_pkt->packet_type = RTE_PTYPE_L3_IPV6;
+#else
rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
} else {
/* Payload */
hdr_rx_pkt = *rx_pkt_bucket;
hdr_rx_pkt->pkt_len += bytes_written;
if (ipv4) {
+#ifdef RTE_NEXT_ABI
+ hdr_rx_pkt->packet_type =
+ RTE_PTYPE_L3_IPV4;
+#else
hdr_rx_pkt->ol_flags |= PKT_RX_IPV4_HDR;
+#endif
if (!csum_not_calc) {
if (unlikely(!ipv4_csum_ok))
hdr_rx_pkt->ol_flags |=
@@ -475,7 +496,12 @@ static int enic_rq_indicate_buf(struct vnic_rq *rq,
PKT_RX_L4_CKSUM_BAD;
}
} else if (ipv6)
+#ifdef RTE_NEXT_ABI
+ hdr_rx_pkt->packet_type =
+ RTE_PTYPE_L3_IPV6;
+#else
hdr_rx_pkt->ol_flags |= PKT_RX_IPV6_HDR;
+#endif
}
}
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 00/18] unified packet type
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
` (18 more replies)
0 siblings, 19 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
Currently only 6 bits which are stored in ol_flags are used to indicate
the packet types. This is not enough, as some NIC hardware can recognize
quite a lot of packet types, e.g i40e hardware can recognize more than 150
packet types. Hiding those packet types hides hardware offload capabilities
which could be quite useful for improving performance and for end users.
So an unified packet types are needed to support all possible PMDs. A 16
bits packet_type in mbuf structure can be changed to 32 bits and used for
this purpose. In addition, all packet types stored in ol_flag field should
be deleted at all, and 6 bits of ol_flags can be save as the benifit.
Initially, 32 bits of packet_type can be divided into several sub fields
to indicate different packet type information of a packet. The initial
design is to divide those bits into fields for L2 types, L3 types, L4 types,
tunnel types, inner L2 types, inner L3 types and inner L4 types. All PMDs
should translate the offloaded packet types into these 7 fields of
information, for user applications.
To avoid breaking ABI compatibility, currently all the code changes for
unified packet type are disabled at compile time by default. Users can
enable it manually by defining the macro of RTE_NEXT_ABI. The code changes
will be valid by default in a future release, and the old version will be
deleted accordingly, after the ABI change process is done.
Note that this patch set should be integrated after another patch set for
'[PATCH v3 0/7] support i40e QinQ stripping and insertion', to clearly
solve the conflict during integration. As both patch sets modified
'struct rte_mbuf', and the final layout of the 'struct rte_mbuf' is key to
vectorized ixgbe PMD.
v2 changes:
* Enlarged the packet_type field from 16 bits to 32 bits.
* Redefined the packet type sub-fields.
* Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
* Used redefined packet types and enlarged packet_type field for all PMDs
and corresponding applications.
* Removed changes in bond and its relevant application, as there is no need
at all according to the recent bond changes.
v3 changes:
* Put the mbuf layout changes into a single patch.
* Put vector ixgbe changes right after mbuf changes.
* Disabled vector ixgbe PMD by default, as mbuf layout changed, and then
re-enabled it after vector ixgbe PMD updated.
* Put the definitions of unified packet type into a single patch.
* Minor bug fixes and enhancements in l3fwd example.
v4 changes:
* Added detailed description of each packet types.
* Supported unified packet type of fm10k.
* Added printing logs of packet types of each received packet for rxonly
mode in testpmd.
* Removed several useless code lines which block packet type unification from
app/test/packet_burst_generator.c.
v5 changes:
* Added more detailed description for each packet types, together with examples.
* Rolled back the macro definitions of RX packet flags, for ABI compitability.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
* Integrated with patch set for '[PATCH v3 0/7] support i40e QinQ stripping
and insertion', to clearly solve the conflicts during merging.
Helin Zhang (18):
mbuf: redefine packet_type in rte_mbuf
ixgbe: support unified packet type in vectorized PMD
mbuf: add definitions of unified packet types
e1000: replace bit mask based packet type with unified packet type
ixgbe: replace bit mask based packet type with unified packet type
i40e: replace bit mask based packet type with unified packet type
enic: replace bit mask based packet type with unified packet type
vmxnet3: replace bit mask based packet type with unified packet type
fm10k: replace bit mask based packet type with unified packet type
app/test-pipeline: replace bit mask based packet type with unified
packet type
app/testpmd: replace bit mask based packet type with unified packet
type
app/test: Remove useless code
examples/ip_fragmentation: replace bit mask based packet type with
unified packet type
examples/ip_reassembly: replace bit mask based packet type with
unified packet type
examples/l3fwd-acl: replace bit mask based packet type with unified
packet type
examples/l3fwd-power: replace bit mask based packet type with unified
packet type
examples/l3fwd: replace bit mask based packet type with unified packet
type
mbuf: remove old packet type bit masks
app/test-pipeline/pipeline_hash.c | 13 +
app/test-pmd/csumonly.c | 14 +
app/test-pmd/rxonly.c | 183 +++++++
app/test/packet_burst_generator.c | 6 +-
drivers/net/e1000/igb_rxtx.c | 102 ++++
drivers/net/enic/enic_main.c | 26 +
drivers/net/fm10k/fm10k_rxtx.c | 27 ++
drivers/net/i40e/i40e_rxtx.c | 528 +++++++++++++++++++++
drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++
drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 ++-
drivers/net/vmxnet3/vmxnet3_rxtx.c | 8 +
examples/ip_fragmentation/main.c | 9 +
examples/ip_reassembly/main.c | 9 +
examples/l3fwd-acl/main.c | 29 +-
examples/l3fwd-power/main.c | 8 +
examples/l3fwd/main.c | 123 ++++-
.../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 +
lib/librte_mbuf/rte_mbuf.c | 4 +
lib/librte_mbuf/rte_mbuf.h | 514 ++++++++++++++++++++
19 files changed, 1834 insertions(+), 13 deletions(-)
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 05/18] ixgbe: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (3 preceding siblings ...)
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 04/18] e1000: replace bit mask based packet type with unified packet type Helin Zhang
@ 2015-06-19 8:14 3% ` Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 06/18] i40e: " Helin Zhang
` (13 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet type among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Note that around 2.5% performance drop (64B) was observed of doing
4 ports (1 port per 82599 card) IO forwarding on the same SNB core.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/ixgbe/ixgbe_rxtx.c | 163 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 041c544..7b5792b 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -855,6 +855,110 @@ end_of_tx:
* RX functions
*
**********************************************************************/
+#ifdef RTE_NEXT_ABI
+#define IXGBE_PACKET_TYPE_IPV4 0X01
+#define IXGBE_PACKET_TYPE_IPV4_TCP 0X11
+#define IXGBE_PACKET_TYPE_IPV4_UDP 0X21
+#define IXGBE_PACKET_TYPE_IPV4_SCTP 0X41
+#define IXGBE_PACKET_TYPE_IPV4_EXT 0X03
+#define IXGBE_PACKET_TYPE_IPV4_EXT_SCTP 0X43
+#define IXGBE_PACKET_TYPE_IPV6 0X04
+#define IXGBE_PACKET_TYPE_IPV6_TCP 0X14
+#define IXGBE_PACKET_TYPE_IPV6_UDP 0X24
+#define IXGBE_PACKET_TYPE_IPV6_EXT 0X0C
+#define IXGBE_PACKET_TYPE_IPV6_EXT_TCP 0X1C
+#define IXGBE_PACKET_TYPE_IPV6_EXT_UDP 0X2C
+#define IXGBE_PACKET_TYPE_IPV4_IPV6 0X05
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_TCP 0X15
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_UDP 0X25
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT 0X0D
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D
+#define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D
+#define IXGBE_PACKET_TYPE_MAX 0X80
+#define IXGBE_PACKET_TYPE_MASK 0X7F
+#define IXGBE_PACKET_TYPE_SHIFT 0X04
+static inline uint32_t
+ixgbe_rxd_pkt_info_to_pkt_type(uint16_t pkt_info)
+{
+ static const uint32_t
+ ptype_table[IXGBE_PACKET_TYPE_MAX] __rte_cache_aligned = {
+ [IXGBE_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4,
+ [IXGBE_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [IXGBE_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IXGBE_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ [IXGBE_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP,
+ [IXGBE_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP,
+ [IXGBE_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP,
+ [IXGBE_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP,
+ };
+ if (unlikely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF))
+ return RTE_PTYPE_UNKNOWN;
+
+ pkt_info = (pkt_info >> IXGBE_PACKET_TYPE_SHIFT) &
+ IXGBE_PACKET_TYPE_MASK;
+
+ return ptype_table[pkt_info];
+}
+
+static inline uint64_t
+ixgbe_rxd_pkt_info_to_pkt_flags(uint16_t pkt_info)
+{
+ static uint64_t ip_rss_types_map[16] __rte_cache_aligned = {
+ 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH,
+ 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH,
+ PKT_RX_RSS_HASH, 0, 0, 0,
+ 0, 0, 0, PKT_RX_FDIR,
+ };
+#ifdef RTE_LIBRTE_IEEE1588
+ static uint64_t ip_pkt_etqf_map[8] = {
+ 0, 0, 0, PKT_RX_IEEE1588_PTP,
+ 0, 0, 0, 0,
+ };
+
+ if (likely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF))
+ return ip_pkt_etqf_map[(pkt_info >> 4) & 0X07] |
+ ip_rss_types_map[pkt_info & 0XF];
+ else
+ return ip_rss_types_map[pkt_info & 0XF];
+#else
+ return ip_rss_types_map[pkt_info & 0XF];
+#endif
+}
+#else /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
{
@@ -890,6 +994,7 @@ rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
#endif
return pkt_flags | ip_rss_types_map[hl_tp_rs & 0xF];
}
+#endif /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_status_to_pkt_flags(uint32_t rx_status)
@@ -945,7 +1050,13 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
struct rte_mbuf *mb;
uint16_t pkt_len;
uint64_t pkt_flags;
+#ifdef RTE_NEXT_ABI
+ int nb_dd;
+ uint32_t s[LOOK_AHEAD];
+ uint16_t pkt_info[LOOK_AHEAD];
+#else
int s[LOOK_AHEAD], nb_dd;
+#endif /* RTE_NEXT_ABI */
int i, j, nb_rx = 0;
@@ -968,6 +1079,12 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
for (j = LOOK_AHEAD-1; j >= 0; --j)
s[j] = rxdp[j].wb.upper.status_error;
+#ifdef RTE_NEXT_ABI
+ for (j = LOOK_AHEAD-1; j >= 0; --j)
+ pkt_info[j] = rxdp[j].wb.lower.lo_dword.
+ hs_rss.pkt_info;
+#endif /* RTE_NEXT_ABI */
+
/* Compute how many status bits were set */
nb_dd = 0;
for (j = 0; j < LOOK_AHEAD; ++j)
@@ -984,12 +1101,22 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].wb.upper.vlan);
/* convert descriptor fields to rte mbuf flags */
+#ifdef RTE_NEXT_ABI
+ pkt_flags = rx_desc_status_to_pkt_flags(s[j]);
+ pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
+ pkt_flags |=
+ ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]);
+ mb->ol_flags = pkt_flags;
+ mb->packet_type =
+ ixgbe_rxd_pkt_info_to_pkt_type(pkt_info[j]);
+#else /* RTE_NEXT_ABI */
pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(
rxdp[j].wb.lower.lo_dword.data);
/* reuse status field from scan list */
pkt_flags |= rx_desc_status_to_pkt_flags(s[j]);
pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
mb->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
mb->hash.rss = rxdp[j].wb.lower.hi_dword.rss;
@@ -1206,7 +1333,11 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
union ixgbe_adv_rx_desc rxd;
uint64_t dma_addr;
uint32_t staterr;
+#ifdef RTE_NEXT_ABI
+ uint32_t pkt_info;
+#else
uint32_t hlen_type_rss;
+#endif
uint16_t pkt_len;
uint16_t rx_id;
uint16_t nb_rx;
@@ -1324,6 +1455,19 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
rxm->data_len = pkt_len;
rxm->port = rxq->port_id;
+#ifdef RTE_NEXT_ABI
+ pkt_info = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.hs_rss.
+ pkt_info);
+ /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
+ rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
+
+ pkt_flags = rx_desc_status_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags |
+ ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info);
+ rxm->ol_flags = pkt_flags;
+ rxm->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info);
+#else /* RTE_NEXT_ABI */
hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data);
/* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */
rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
@@ -1332,6 +1476,7 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
rxm->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
rxm->hash.rss = rxd.wb.lower.hi_dword.rss;
@@ -1405,6 +1550,23 @@ ixgbe_fill_cluster_head_buf(
uint8_t port_id,
uint32_t staterr)
{
+#ifdef RTE_NEXT_ABI
+ uint16_t pkt_info;
+ uint64_t pkt_flags;
+
+ head->port = port_id;
+
+ /* The vlan_tci field is only valid when PKT_RX_VLAN_PKT is
+ * set in the pkt_flags field.
+ */
+ head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan);
+ pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.hs_rss.pkt_info);
+ pkt_flags = rx_desc_status_to_pkt_flags(staterr);
+ pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info);
+ head->ol_flags = pkt_flags;
+ head->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info);
+#else /* RTE_NEXT_ABI */
uint32_t hlen_type_rss;
uint64_t pkt_flags;
@@ -1420,6 +1582,7 @@ ixgbe_fill_cluster_head_buf(
pkt_flags |= rx_desc_status_to_pkt_flags(staterr);
pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
head->ol_flags = pkt_flags;
+#endif /* RTE_NEXT_ABI */
if (likely(pkt_flags & PKT_RX_RSS_HASH))
head->hash.rss = rte_le_to_cpu_32(desc->wb.lower.hi_dword.rss);
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 04/18] e1000: replace bit mask based packet type with unified packet type
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
` (2 preceding siblings ...)
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 03/18] mbuf: add definitions of unified packet types Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 05/18] ixgbe: " Helin Zhang
` (14 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify packet types among all PMDs, bit masks of packet type for
'ol_flags' are replaced by unified packet type.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
drivers/net/e1000/igb_rxtx.c | 102 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index 43d6703..d1c2ef8 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -590,6 +590,99 @@ eth_igb_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
* RX functions
*
**********************************************************************/
+#ifdef RTE_NEXT_ABI
+#define IGB_PACKET_TYPE_IPV4 0X01
+#define IGB_PACKET_TYPE_IPV4_TCP 0X11
+#define IGB_PACKET_TYPE_IPV4_UDP 0X21
+#define IGB_PACKET_TYPE_IPV4_SCTP 0X41
+#define IGB_PACKET_TYPE_IPV4_EXT 0X03
+#define IGB_PACKET_TYPE_IPV4_EXT_SCTP 0X43
+#define IGB_PACKET_TYPE_IPV6 0X04
+#define IGB_PACKET_TYPE_IPV6_TCP 0X14
+#define IGB_PACKET_TYPE_IPV6_UDP 0X24
+#define IGB_PACKET_TYPE_IPV6_EXT 0X0C
+#define IGB_PACKET_TYPE_IPV6_EXT_TCP 0X1C
+#define IGB_PACKET_TYPE_IPV6_EXT_UDP 0X2C
+#define IGB_PACKET_TYPE_IPV4_IPV6 0X05
+#define IGB_PACKET_TYPE_IPV4_IPV6_TCP 0X15
+#define IGB_PACKET_TYPE_IPV4_IPV6_UDP 0X25
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT 0X0D
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D
+#define IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D
+#define IGB_PACKET_TYPE_MAX 0X80
+#define IGB_PACKET_TYPE_MASK 0X7F
+#define IGB_PACKET_TYPE_SHIFT 0X04
+static inline uint32_t
+igb_rxd_pkt_info_to_pkt_type(uint16_t pkt_info)
+{
+ static const uint32_t
+ ptype_table[IGB_PACKET_TYPE_MAX] __rte_cache_aligned = {
+ [IGB_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV4,
+ [IGB_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT,
+ [IGB_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_MAC | RTE_PTYPE_L3_IPV6,
+ [IGB_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IGB_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ [IGB_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP,
+ [IGB_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP,
+ [IGB_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP,
+ [IGB_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP,
+ [IGB_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP,
+ [IGB_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_MAC |
+ RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP,
+ };
+ if (unlikely(pkt_info & E1000_RXDADV_PKTTYPE_ETQF))
+ return RTE_PTYPE_UNKNOWN;
+
+ pkt_info = (pkt_info >> IGB_PACKET_TYPE_SHIFT) & IGB_PACKET_TYPE_MASK;
+
+ return ptype_table[pkt_info];
+}
+
+static inline uint64_t
+rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
+{
+ uint64_t pkt_flags = ((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH;
+
+#if defined(RTE_LIBRTE_IEEE1588)
+ static uint32_t ip_pkt_etqf_map[8] = {
+ 0, 0, 0, PKT_RX_IEEE1588_PTP,
+ 0, 0, 0, 0,
+ };
+
+ pkt_flags |= ip_pkt_etqf_map[(hl_tp_rs >> 4) & 0x07];
+#endif
+
+ return pkt_flags;
+}
+#else /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
{
@@ -617,6 +710,7 @@ rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs)
#endif
return pkt_flags | (((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH);
}
+#endif /* RTE_NEXT_ABI */
static inline uint64_t
rx_desc_status_to_pkt_flags(uint32_t rx_status)
@@ -790,6 +884,10 @@ eth_igb_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
rxm->ol_flags = pkt_flags;
+#ifdef RTE_NEXT_ABI
+ rxm->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.lower.
+ lo_dword.hs_rss.pkt_info);
+#endif
/*
* Store the mbuf address into the next entry of the array
@@ -1024,6 +1122,10 @@ eth_igb_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr);
pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
first_seg->ol_flags = pkt_flags;
+#ifdef RTE_NEXT_ABI
+ first_seg->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.
+ lower.lo_dword.hs_rss.pkt_info);
+#endif
/* Prefetch data of first segment, if configured to do so. */
rte_packet_prefetch((char *)first_seg->buf_addr +
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v7 03/18] mbuf: add definitions of unified packet types
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 02/18] ixgbe: support unified packet type in vectorized PMD Helin Zhang
@ 2015-06-19 8:14 3% ` Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 04/18] e1000: replace bit mask based packet type with unified packet type Helin Zhang
` (15 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
As there are only 6 bit flags in ol_flags for indicating packet
types, which is not enough to describe all the possible packet
types hardware can recognize. For example, i40e hardware can
recognize more than 150 packet types. Unified packet type is
composed of L2 type, L3 type, L4 type, tunnel type, inner L2 type,
inner L3 type and inner L4 type fields, and can be stored in
'struct rte_mbuf' of 32 bits field 'packet_type'.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_mbuf/rte_mbuf.h | 487 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 487 insertions(+)
v3 changes:
* Put the definitions of unified packet type into a single patch.
v4 changes:
* Added detailed description of each packet types.
v5 changes:
* Re-worded the commit logs.
* Added more detailed description for all packet types, together with examples.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index aa55769..5e7cc26 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -201,6 +201,493 @@ extern "C" {
/* Use final bit of flags to indicate a control mbuf */
#define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control data */
+#ifdef RTE_NEXT_ABI
+/*
+ * 32 bits are divided into several fields to mark packet types. Note that
+ * each field is indexical.
+ * - Bit 3:0 is for L2 types.
+ * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
+ * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
+ * - Bit 15:12 is for tunnel types.
+ * - Bit 19:16 is for inner L2 types.
+ * - Bit 23:20 is for inner L3 types.
+ * - Bit 27:24 is for inner L4 types.
+ * - Bit 31:28 is reserved.
+ *
+ * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT,
+ * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP
+ * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
+ *
+ * Note that L3 types values are selected for checking IPV4/IPV6 header from
+ * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and
+ * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
+ *
+ * Note that the packet types of the same packet recognized by different
+ * hardware may be different, as different hardware may have different
+ * capability of packet type recognition.
+ *
+ * examples:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=0x29
+ * | 'version'=6, 'next header'=0x3A
+ * | 'ICMPv6 header'>
+ * will be recognized on i40e hardware as packet type combination of,
+ * RTE_PTYPE_L2_MAC |
+ * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ * RTE_PTYPE_TUNNEL_IP |
+ * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_INNER_L4_ICMP.
+ *
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x2F
+ * | 'GRE header'
+ * | 'version'=6, 'next header'=0x11
+ * | 'UDP header'>
+ * will be recognized on i40e hardware as packet type combination of,
+ * RTE_PTYPE_L2_MAC |
+ * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_TUNNEL_GRENAT |
+ * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ * RTE_PTYPE_INNER_L4_UDP.
+ */
+#define RTE_PTYPE_UNKNOWN 0x00000000
+/**
+ * MAC (Media Access Control) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=[0x0800|0x86DD|others]>
+ */
+#define RTE_PTYPE_L2_MAC 0x00000001
+/**
+ * MAC (Media Access Control) packet type for time sync.
+ *
+ * Packet format:
+ * <'ether type'=0x88F7>
+ */
+#define RTE_PTYPE_L2_MAC_TIMESYNC 0x00000002
+/**
+ * ARP (Address Resolution Protocol) packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0806>
+ */
+#define RTE_PTYPE_L2_ARP 0x00000003
+/**
+ * LLDP (Link Layer Discovery Protocol) packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x88CC>
+ */
+#define RTE_PTYPE_L2_LLDP 0x00000004
+/**
+ * Mask of layer 2 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L2_MASK 0x0000000f
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and does not contain any
+ * header option.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=5>
+ */
+#define RTE_PTYPE_L3_IPV4 0x00000010
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and contains header
+ * options.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[6-15], 'options'>
+ */
+#define RTE_PTYPE_L3_IPV4_EXT 0x00000030
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and does not contain any
+ * extension header.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x3B>
+ */
+#define RTE_PTYPE_L3_IPV6 0x00000040
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for outer packet for tunneling cases, and may or maynot contain
+ * header options.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[5-15], <'options'>>
+ */
+#define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and contains extension
+ * headers.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * 'extension headers'>
+ */
+#define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for outer packet for tunneling cases, and may or maynot contain
+ * extension headers.
+ *
+ * Packet format:
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * <'extension headers'>>
+ */
+#define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
+/**
+ * Mask of layer 3 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L3_MASK 0x000000f0
+/**
+ * TCP (Transmission Control Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=6, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=6>
+ */
+#define RTE_PTYPE_L4_TCP 0x00000100
+/**
+ * UDP (User Datagram Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17>
+ */
+#define RTE_PTYPE_L4_UDP 0x00000200
+/**
+ * Fragmented IP (Internet Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * It refers to those packets of any IP types, which can be recognized as
+ * fragmented. A fragmented packet cannot be recognized as any other L4 types
+ * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP,
+ * RTE_PTYPE_L4_NONFRAG).
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'MF'=1>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=44>
+ */
+#define RTE_PTYPE_L4_FRAG 0x00000300
+/**
+ * SCTP (Stream Control Transmission Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=132, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=132>
+ */
+#define RTE_PTYPE_L4_SCTP 0x00000400
+/**
+ * ICMP (Internet Control Message Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=1, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=1>
+ */
+#define RTE_PTYPE_L4_ICMP 0x00000500
+/**
+ * Non-fragmented IP (Internet Protocol) packet type.
+ * It is used for outer packet for tunneling cases.
+ *
+ * It refers to those packets of any IP types, while cannot be recognized as
+ * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP,
+ * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP).
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'!=[6|17|44|132|1]>
+ */
+#define RTE_PTYPE_L4_NONFRAG 0x00000600
+/**
+ * Mask of layer 4 packet types.
+ * It is used for outer packet for tunneling cases.
+ */
+#define RTE_PTYPE_L4_MASK 0x00000f00
+/**
+ * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=[4|41]>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[4|41]>
+ */
+#define RTE_PTYPE_TUNNEL_IP 0x00001000
+/**
+ * GRE (Generic Routing Encapsulation) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=47>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=47>
+ */
+#define RTE_PTYPE_TUNNEL_GRE 0x00002000
+/**
+ * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17
+ * | 'destination port'=4798>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17
+ * | 'destination port'=4798>
+ */
+#define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
+/**
+ * NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling
+ * packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=47
+ * | 'protocol type'=0x6558>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=47
+ * | 'protocol type'=0x6558'>
+ */
+#define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
+/**
+ * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type.
+ *
+ * Packet format:
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17
+ * | 'destination port'=6081>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17
+ * | 'destination port'=6081>
+ */
+#define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
+/**
+ * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area
+ * Network) or GRE (Generic Routing Encapsulation) could be recognized as this
+ * packet type, if they can not be recognized independently as of hardware
+ * capability.
+ */
+#define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
+/**
+ * Mask of tunneling packet types.
+ */
+#define RTE_PTYPE_TUNNEL_MASK 0x0000f000
+/**
+ * MAC (Media Access Control) packet type.
+ * It is used for inner packet type only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=[0x800|0x86DD]>
+ */
+#define RTE_PTYPE_INNER_L2_MAC 0x00010000
+/**
+ * MAC (Media Access Control) packet type with VLAN (Virtual Local Area
+ * Network) tag.
+ *
+ * Packet format (inner only):
+ * <'ether type'=[0x800|0x86DD], vlan=[1-4095]>
+ */
+#define RTE_PTYPE_INNER_L2_MAC_VLAN 0x00020000
+/**
+ * Mask of inner layer 2 packet types.
+ */
+#define RTE_PTYPE_INNER_L2_MASK 0x000f0000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and does not contain any header option.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=5>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4 0x00100000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and contains header options.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[6-15], 'options'>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and does not contain any extension header.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=0x3B>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6 0x00300000
+/**
+ * IP (Internet Protocol) version 4 packet type.
+ * It is used for inner packet only, and may or maynot contain header options.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'ihl'=[5-15], <'options'>>
+ */
+#define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and contains extension headers.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * 'extension headers'>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
+/**
+ * IP (Internet Protocol) version 6 packet type.
+ * It is used for inner packet only, and may or maynot contain extension
+ * headers.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87],
+ * <'extension headers'>>
+ */
+#define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
+/**
+ * Mask of inner layer 3 packet types.
+ */
+#define RTE_PTYPE_INNER_INNER_L3_MASK 0x00f00000
+/**
+ * TCP (Transmission Control Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=6, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=6>
+ */
+#define RTE_PTYPE_INNER_L4_TCP 0x01000000
+/**
+ * UDP (User Datagram Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=17, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=17>
+ */
+#define RTE_PTYPE_INNER_L4_UDP 0x02000000
+/**
+ * Fragmented IP (Internet Protocol) packet type.
+ * It is used for inner packet only, and may or maynot have layer 4 packet.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'MF'=1>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=44>
+ */
+#define RTE_PTYPE_INNER_L4_FRAG 0x03000000
+/**
+ * SCTP (Stream Control Transmission Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=132, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=132>
+ */
+#define RTE_PTYPE_INNER_L4_SCTP 0x04000000
+/**
+ * ICMP (Internet Control Message Protocol) packet type.
+ * It is used for inner packet only.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'=1, 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'=1>
+ */
+#define RTE_PTYPE_INNER_L4_ICMP 0x05000000
+/**
+ * Non-fragmented IP (Internet Protocol) packet type.
+ * It is used for inner packet only, and may or maynot have other unknown layer
+ * 4 packet types.
+ *
+ * Packet format (inner only):
+ * <'ether type'=0x0800
+ * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0>
+ * or,
+ * <'ether type'=0x86DD
+ * | 'version'=6, 'next header'!=[6|17|44|132|1]>
+ */
+#define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
+/**
+ * Mask of inner layer 4 packet types.
+ */
+#define RTE_PTYPE_INNER_L4_MASK 0x0f000000
+
+/**
+ * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
+ * one, bit 4 is selected to be used for IPv4 only. Then checking bit 4 can
+ * determin if it is an IPV4 packet.
+ */
+#define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
+
+/**
+ * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by
+ * one, bit 6 is selected to be used for IPv4 only. Then checking bit 6 can
+ * determin if it is an IPV4 packet.
+ */
+#define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
+
+/* Check if it is a tunneling packet */
+#define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & RTE_PTYPE_TUNNEL_MASK)
+#endif /* RTE_NEXT_ABI */
+
/**
* Get the name of a RX offload flag
*
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 02/18] ixgbe: support unified packet type in vectorized PMD
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
@ 2015-06-19 8:14 3% ` Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 03/18] mbuf: add definitions of unified packet types Helin Zhang
` (16 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
To unify the packet type, bit masks of packet type for ol_flags are
replaced. In addition, more packet types (UDP, TCP and SCTP) are
supported in vectorized ixgbe PMD.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Note that around 2% performance drop (64B) was observed of doing 4
ports (1 port per 82599 card) IO forwarding on the same SNB core.
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
config/common_linuxapp | 2 +-
drivers/net/ixgbe/ixgbe_rxtx_vec.c | 75 +++++++++++++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 3 deletions(-)
v2 changes:
* Used redefined packet types and enlarged packet_type field in mbuf.
v3 changes:
* Put vector ixgbe changes right after mbuf changes.
* Enabled vector ixgbe PMD by default together with changes for updated
vector PMD.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 617d4a1..5deb55a 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -167,7 +167,7 @@ CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
CONFIG_RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC=y
-CONFIG_RTE_IXGBE_INC_VECTOR=n
+CONFIG_RTE_IXGBE_INC_VECTOR=y
CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y
#
diff --git a/drivers/net/ixgbe/ixgbe_rxtx_vec.c b/drivers/net/ixgbe/ixgbe_rxtx_vec.c
index abd10f6..ccea7cd 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx_vec.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx_vec.c
@@ -134,6 +134,12 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
*/
#ifdef RTE_IXGBE_RX_OLFLAGS_ENABLE
+#ifdef RTE_NEXT_ABI
+#define OLFLAGS_MASK_V (((uint64_t)PKT_RX_VLAN_PKT << 48) | \
+ ((uint64_t)PKT_RX_VLAN_PKT << 32) | \
+ ((uint64_t)PKT_RX_VLAN_PKT << 16) | \
+ ((uint64_t)PKT_RX_VLAN_PKT))
+#else
#define OLFLAGS_MASK ((uint16_t)(PKT_RX_VLAN_PKT | PKT_RX_IPV4_HDR |\
PKT_RX_IPV4_HDR_EXT | PKT_RX_IPV6_HDR |\
PKT_RX_IPV6_HDR_EXT))
@@ -142,11 +148,26 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
((uint64_t)OLFLAGS_MASK << 16) | \
((uint64_t)OLFLAGS_MASK))
#define PTYPE_SHIFT (1)
+#endif /* RTE_NEXT_ABI */
+
#define VTAG_SHIFT (3)
static inline void
desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
{
+#ifdef RTE_NEXT_ABI
+ __m128i vtag0, vtag1;
+ union {
+ uint16_t e[4];
+ uint64_t dword;
+ } vol;
+
+ vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]);
+ vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]);
+ vtag1 = _mm_unpacklo_epi32(vtag0, vtag1);
+ vtag1 = _mm_srli_epi16(vtag1, VTAG_SHIFT);
+ vol.dword = _mm_cvtsi128_si64(vtag1) & OLFLAGS_MASK_V;
+#else
__m128i ptype0, ptype1, vtag0, vtag1;
union {
uint16_t e[4];
@@ -166,6 +187,7 @@ desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
ptype1 = _mm_or_si128(ptype1, vtag1);
vol.dword = _mm_cvtsi128_si64(ptype1) & OLFLAGS_MASK_V;
+#endif /* RTE_NEXT_ABI */
rx_pkts[0]->ol_flags = vol.e[0];
rx_pkts[1]->ol_flags = vol.e[1];
@@ -196,6 +218,18 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
int pos;
uint64_t var;
__m128i shuf_msk;
+#ifdef RTE_NEXT_ABI
+ __m128i crc_adjust = _mm_set_epi16(
+ 0, 0, 0, /* ignore non-length fields */
+ -rxq->crc_len, /* sub crc on data_len */
+ 0, /* ignore high-16bits of pkt_len */
+ -rxq->crc_len, /* sub crc on pkt_len */
+ 0, 0 /* ignore pkt_type field */
+ );
+ __m128i dd_check, eop_check;
+ __m128i desc_mask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFF07F0);
+#else
__m128i crc_adjust = _mm_set_epi16(
0, 0, 0, 0, /* ignore non-length fields */
0, /* ignore high-16bits of pkt_len */
@@ -204,6 +238,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
0 /* ignore pkt_type field */
);
__m128i dd_check, eop_check;
+#endif /* RTE_NEXT_ABI */
if (unlikely(nb_pkts < RTE_IXGBE_VPMD_RX_BURST))
return 0;
@@ -232,6 +267,18 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
eop_check = _mm_set_epi64x(0x0000000200000002LL, 0x0000000200000002LL);
/* mask to shuffle from desc. to mbuf */
+#ifdef RTE_NEXT_ABI
+ shuf_msk = _mm_set_epi8(
+ 7, 6, 5, 4, /* octet 4~7, 32bits rss */
+ 15, 14, /* octet 14~15, low 16 bits vlan_macip */
+ 13, 12, /* octet 12~13, 16 bits data_len */
+ 0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */
+ 13, 12, /* octet 12~13, low 16 bits pkt_len */
+ 0xFF, 0xFF, /* skip high 16 bits pkt_type */
+ 1, /* octet 1, 8 bits pkt_type field */
+ 0 /* octet 0, 4 bits offset 4 pkt_type field */
+ );
+#else
shuf_msk = _mm_set_epi8(
7, 6, 5, 4, /* octet 4~7, 32bits rss */
0xFF, 0xFF, /* skip high 16 bits vlan_macip, zero out */
@@ -241,18 +288,28 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
13, 12, /* octet 12~13, 16 bits data_len */
0xFF, 0xFF /* skip pkt_type field */
);
+#endif /* RTE_NEXT_ABI */
/* Cache is empty -> need to scan the buffer rings, but first move
* the next 'n' mbufs into the cache */
sw_ring = &rxq->sw_ring[rxq->rx_tail];
- /*
- * A. load 4 packet in one loop
+#ifdef RTE_NEXT_ABI
+ /* A. load 4 packet in one loop
+ * [A*. mask out 4 unused dirty field in desc]
* B. copy 4 mbuf point from swring to rx_pkts
* C. calc the number of DD bits among the 4 packets
* [C*. extract the end-of-packet bit, if requested]
* D. fill info. from desc to mbuf
*/
+#else
+ /* A. load 4 packet in one loop
+ * B. copy 4 mbuf point from swring to rx_pkts
+ * C. calc the number of DD bits among the 4 packets
+ * [C*. extract the end-of-packet bit, if requested]
+ * D. fill info. from desc to mbuf
+ */
+#endif /* RTE_NEXT_ABI */
for (pos = 0, nb_pkts_recd = 0; pos < RTE_IXGBE_VPMD_RX_BURST;
pos += RTE_IXGBE_DESCS_PER_LOOP,
rxdp += RTE_IXGBE_DESCS_PER_LOOP) {
@@ -289,6 +346,16 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
/* B.2 copy 2 mbuf point into rx_pkts */
_mm_storeu_si128((__m128i *)&rx_pkts[pos+2], mbp2);
+#ifdef RTE_NEXT_ABI
+ /* A* mask out 0~3 bits RSS type */
+ descs[3] = _mm_and_si128(descs[3], desc_mask);
+ descs[2] = _mm_and_si128(descs[2], desc_mask);
+
+ /* A* mask out 0~3 bits RSS type */
+ descs[1] = _mm_and_si128(descs[1], desc_mask);
+ descs[0] = _mm_and_si128(descs[0], desc_mask);
+#endif /* RTE_NEXT_ABI */
+
/* avoid compiler reorder optimization */
rte_compiler_barrier();
@@ -301,7 +368,11 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
/* C.1 4=>2 filter staterr info only */
sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]);
+#ifdef RTE_NEXT_ABI
+ /* set ol_flags with vlan packet type */
+#else
/* set ol_flags with packet type and vlan tag */
+#endif /* RTE_NEXT_ABI */
desc_to_olflags_v(descs, &rx_pkts[pos]);
/* D.2 pkt 3,4 set in_port/nb_seg and remove crc */
--
1.9.3
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH v7 01/18] mbuf: redefine packet_type in rte_mbuf
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
@ 2015-06-19 8:14 4% ` Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 02/18] ixgbe: support unified packet type in vectorized PMD Helin Zhang
` (17 subsequent siblings)
18 siblings, 0 replies; 200+ results
From: Helin Zhang @ 2015-06-19 8:14 UTC (permalink / raw)
To: dev
In order to unify the packet type, the field of 'packet_type' in
'struct rte_mbuf' needs to be extended from 16 to 32 bits.
Accordingly, some fields in 'struct rte_mbuf' are re-organized to
support this change for Vector PMD. As 'struct rte_kni_mbuf' for
KNI should be right mapped to 'struct rte_mbuf', it should be
modified accordingly. In addition, Vector PMD of ixgbe is disabled
by default, as 'struct rte_mbuf' changed.
To avoid breaking ABI compatibility, all the changes would be
enabled by RTE_NEXT_ABI, which is disabled by default.
Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
config/common_linuxapp | 2 +-
.../linuxapp/eal/include/exec-env/rte_kni_common.h | 6 ++++++
lib/librte_mbuf/rte_mbuf.h | 23 ++++++++++++++++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
v2 changes:
* Enlarged the packet_type field from 16 bits to 32 bits.
* Redefined the packet type sub-fields.
* Updated the 'struct rte_kni_mbuf' for KNI according to the mbuf changes.
v3 changes:
* Put the mbuf layout changes into a single patch.
* Disabled vector ixgbe PMD by default, as mbuf layout changed.
v5 changes:
* Re-worded the commit logs.
v6 changes:
* Disabled the code changes for unified packet type by default, to
avoid breaking ABI compatibility.
v7 changes:
* Renamed RTE_UNIFIED_PKT_TYPE to RTE_NEXT_ABI.
* Integrated with changes of QinQ stripping/insertion.
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 5deb55a..617d4a1 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -167,7 +167,7 @@ CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n
CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n
CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n
CONFIG_RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC=y
-CONFIG_RTE_IXGBE_INC_VECTOR=y
+CONFIG_RTE_IXGBE_INC_VECTOR=n
CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y
#
diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
index 1e55c2d..e9f38bd 100644
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
@@ -117,9 +117,15 @@ struct rte_kni_mbuf {
uint16_t data_off; /**< Start address of data in segment buffer. */
char pad1[4];
uint64_t ol_flags; /**< Offload features. */
+#ifdef RTE_NEXT_ABI
+ char pad2[4];
+ uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
+ uint16_t data_len; /**< Amount of data in segment buffer. */
+#else
char pad2[2];
uint16_t data_len; /**< Amount of data in segment buffer. */
uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */
+#endif
/* fields on second cache line */
char pad3[8] __attribute__((__aligned__(RTE_CACHE_LINE_SIZE)));
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index a0f3d3b..aa55769 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -275,6 +275,28 @@ struct rte_mbuf {
/* remaining bytes are set on RX when pulling packet from descriptor */
MARKER rx_descriptor_fields1;
+#ifdef RTE_NEXT_ABI
+ /*
+ * The packet type, which is the combination of outer/inner L2, L3, L4
+ * and tunnel types.
+ */
+ union {
+ uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */
+ struct {
+ uint32_t l2_type:4; /**< (Outer) L2 type. */
+ uint32_t l3_type:4; /**< (Outer) L3 type. */
+ uint32_t l4_type:4; /**< (Outer) L4 type. */
+ uint32_t tun_type:4; /**< Tunnel type. */
+ uint32_t inner_l2_type:4; /**< Inner L2 type. */
+ uint32_t inner_l3_type:4; /**< Inner L3 type. */
+ uint32_t inner_l4_type:4; /**< Inner L4 type. */
+ };
+ };
+
+ uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
+ uint16_t data_len; /**< Amount of data in segment buffer. */
+ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
+#else
/**
* The packet type, which is used to indicate ordinary packet and also
* tunneled packet format, i.e. each number is represented a type of
@@ -285,6 +307,7 @@ struct rte_mbuf {
uint16_t data_len; /**< Amount of data in segment buffer. */
uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
+#endif
uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */
union {
uint32_t rss; /**< RSS hash result if RSS enabled */
--
1.9.3
^ permalink raw reply [relevance 4%]
* [dpdk-dev] [PATCH v13 14/14] abi: fix v2.1 abi broken issue
2015-06-19 4:00 4% ` [dpdk-dev] [PATCH v13 " Cunming Liang
2015-06-19 4:00 2% ` [dpdk-dev] [PATCH v13 10/14] ethdev: add rx intr enable, disable and ctl functions Cunming Liang
@ 2015-06-19 4:00 10% ` Cunming Liang
1 sibling, 0 replies; 200+ results
From: Cunming Liang @ 2015-06-19 4:00 UTC (permalink / raw)
To: dev; +Cc: shemming, liang-min.wang
RTE_NEXT_ABI will be removed from v2.2. It's only used to avoid ABI(unannounced) broken in v2.1.
The usrs should make sure understand the impact before turning on the feature.
There are two abi changes required in this interrupt patch set.
They're 1) struct rte_intr_handle; 2) struct rte_intr_conf.
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
v13 changes
- Use common RTE_NEXT_ABI to replace RTE_EAL_RX_INTR
v9
- Acked-by: vincent jardin <vincent.jardin@6wind.com>
drivers/net/e1000/igb_ethdev.c | 28 ++++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 41 ++++++++++++-
examples/l3fwd-power/main.c | 3 +-
.../bsdapp/eal/include/exec-env/rte_interrupts.h | 7 +++
lib/librte_eal/linuxapp/eal/eal_interrupts.c | 12 ++++
.../linuxapp/eal/include/exec-env/rte_interrupts.h | 68 +++++++++++++++++++++-
lib/librte_ether/rte_ethdev.c | 2 +
lib/librte_ether/rte_ethdev.h | 32 +++++++++-
8 files changed, 182 insertions(+), 11 deletions(-)
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 56d604a..e6f4ba8 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -96,7 +96,9 @@ static int eth_igb_flow_ctrl_get(struct rte_eth_dev *dev,
static int eth_igb_flow_ctrl_set(struct rte_eth_dev *dev,
struct rte_eth_fc_conf *fc_conf);
static int eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev);
+#ifdef RTE_NEXT_ABI
static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev);
+#endif
static int eth_igb_interrupt_get_status(struct rte_eth_dev *dev);
static int eth_igb_interrupt_action(struct rte_eth_dev *dev);
static void eth_igb_interrupt_handler(struct rte_intr_handle *handle,
@@ -201,11 +203,15 @@ static int eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev,
uint16_t queue_id);
static int eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev,
uint16_t queue_id);
+#ifdef RTE_NEXT_ABI
static void eth_igb_assign_msix_vector(struct e1000_hw *hw, int8_t direction,
uint8_t queue, uint8_t msix_vector);
+#endif
static void eth_igb_configure_msix_intr(struct rte_eth_dev *dev);
+#ifdef RTE_NEXT_ABI
static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector,
uint8_t index, uint8_t offset);
+#endif
/*
* Define VF Stats MACRO for Non "cleared on read" register
@@ -764,7 +770,9 @@ eth_igb_start(struct rte_eth_dev *dev)
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+#ifdef RTE_NEXT_ABI
uint32_t intr_vector = 0;
+#endif
int ret, mask;
uint32_t ctrl_ext;
@@ -805,6 +813,7 @@ eth_igb_start(struct rte_eth_dev *dev)
/* configure PF module if SRIOV enabled */
igb_pf_host_configure(dev);
+#ifdef RTE_NEXT_ABI
/* check and configure queue intr-vector mapping */
if (dev->data->dev_conf.intr_conf.rxq != 0)
intr_vector = dev->data->nb_rx_queues;
@@ -822,6 +831,7 @@ eth_igb_start(struct rte_eth_dev *dev)
return -ENOMEM;
}
}
+#endif
/* confiugre msix for rx interrupt */
eth_igb_configure_msix_intr(dev);
@@ -917,9 +927,11 @@ eth_igb_start(struct rte_eth_dev *dev)
" no intr multiplex\n");
}
+#ifdef RTE_NEXT_ABI
/* check if rxq interrupt is enabled */
if (dev->data->dev_conf.intr_conf.rxq != 0)
eth_igb_rxq_interrupt_setup(dev);
+#endif
/* enable uio/vfio intr/eventfd mapping */
rte_intr_enable(intr_handle);
@@ -1011,12 +1023,14 @@ eth_igb_stop(struct rte_eth_dev *dev)
}
filter_info->twotuple_mask = 0;
+#ifdef RTE_NEXT_ABI
/* Clean datapath event and queue/vec mapping */
rte_intr_efd_disable(intr_handle);
if (intr_handle->intr_vec != NULL) {
rte_free(intr_handle->intr_vec);
intr_handle->intr_vec = NULL;
}
+#endif
}
static void
@@ -1024,7 +1038,9 @@ eth_igb_close(struct rte_eth_dev *dev)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct rte_eth_link link;
+#ifdef RTE_NEXT_ABI
struct rte_pci_device *pci_dev;
+#endif
eth_igb_stop(dev);
e1000_phy_hw_reset(hw);
@@ -1042,11 +1058,13 @@ eth_igb_close(struct rte_eth_dev *dev)
igb_dev_clear_queues(dev);
+#ifdef RTE_NEXT_ABI
pci_dev = dev->pci_dev;
if (pci_dev->intr_handle.intr_vec) {
rte_free(pci_dev->intr_handle.intr_vec);
pci_dev->intr_handle.intr_vec = NULL;
}
+#endif
memset(&link, 0, sizeof(link));
rte_igb_dev_atomic_write_link_status(dev, &link);
@@ -1871,6 +1889,7 @@ eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev)
return 0;
}
+#ifdef RTE_NEXT_ABI
/*
* It clears the interrupt causes and enables the interrupt.
* It will be called once only during nic initialized.
@@ -1898,6 +1917,7 @@ static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev)
return 0;
}
+#endif
/*
* It reads ICR and gets interrupt causes, check it and set a bit flag
@@ -3766,6 +3786,7 @@ eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
return 0;
}
+#ifdef RTE_NEXT_ABI
static void
eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector,
uint8_t index, uint8_t offset)
@@ -3807,6 +3828,7 @@ eth_igb_assign_msix_vector(struct e1000_hw *hw, int8_t direction,
((queue & 0x1) << 4) + 8 * direction);
}
}
+#endif
/*
* Sets up the hardware to generate MSI-X interrupts properly
@@ -3816,18 +3838,21 @@ eth_igb_assign_msix_vector(struct e1000_hw *hw, int8_t direction,
static void
eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
{
+#ifdef RTE_NEXT_ABI
int queue_id;
uint32_t tmpval, regval, intr_mask;
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
uint32_t vec = 0;
+#endif
+ struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
/* won't configure msix register if no mapping is done
* between intr vector and event fd */
if (!rte_intr_dp_is_en(intr_handle))
return;
+#ifdef RTE_NEXT_ABI
/* set interrupt vector for other causes */
if (hw->mac.type == e1000_82575) {
tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -3884,6 +3909,7 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
}
E1000_WRITE_FLUSH(hw);
+#endif
}
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 7b428eb..e3ff015 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -174,7 +174,9 @@ static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
uint16_t reta_size);
static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev);
static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev);
+#ifdef RTE_NEXT_ABI
static int ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
+#endif
static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev);
static void ixgbe_dev_interrupt_handler(struct rte_intr_handle *handle,
@@ -210,8 +212,10 @@ static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
uint16_t queue_id);
static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
uint16_t queue_id);
+#ifdef RTE_NEXT_ABI
static void ixgbevf_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
uint8_t queue, uint8_t msix_vector);
+#endif
static void ixgbevf_configure_msix(struct rte_eth_dev *dev);
/* For Eth VMDQ APIs support */
@@ -234,8 +238,10 @@ static int ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
uint16_t queue_id);
static int ixgbe_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
uint16_t queue_id);
+#ifdef RTE_NEXT_ABI
static void ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
uint8_t queue, uint8_t msix_vector);
+#endif
static void ixgbe_configure_msix(struct rte_eth_dev *dev);
static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
@@ -1487,7 +1493,9 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
struct ixgbe_vf_info *vfinfo =
*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+#ifdef RTE_NEXT_ABI
uint32_t intr_vector = 0;
+#endif
int err, link_up = 0, negotiate = 0;
uint32_t speed = 0;
int mask = 0;
@@ -1520,6 +1528,7 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
/* configure PF module if SRIOV enabled */
ixgbe_pf_host_configure(dev);
+#ifdef RTE_NEXT_ABI
/* check and configure queue intr-vector mapping */
if (dev->data->dev_conf.intr_conf.rxq != 0)
intr_vector = dev->data->nb_rx_queues;
@@ -1538,6 +1547,7 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
return -ENOMEM;
}
}
+#endif
/* confiugre msix for sleep until rx interrupt */
ixgbe_configure_msix(dev);
@@ -1625,9 +1635,11 @@ skip_link_setup:
" no intr multiplex\n");
}
+#ifdef RTE_NEXT_ABI
/* check if rxq interrupt is enabled */
if (dev->data->dev_conf.intr_conf.rxq != 0)
ixgbe_dev_rxq_interrupt_setup(dev);
+#endif
/* enable uio/vfio intr/eventfd mapping */
rte_intr_enable(intr_handle);
@@ -1733,12 +1745,14 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
memset(filter_info->fivetuple_mask, 0,
sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
+#ifdef RTE_NEXT_ABI
/* Clean datapath event and queue/vec mapping */
rte_intr_efd_disable(intr_handle);
if (intr_handle->intr_vec != NULL) {
rte_free(intr_handle->intr_vec);
intr_handle->intr_vec = NULL;
}
+#endif
}
/*
@@ -2341,6 +2355,7 @@ ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev)
* - On success, zero.
* - On failure, a negative value.
*/
+#ifdef RTE_NEXT_ABI
static int
ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
{
@@ -2351,6 +2366,7 @@ ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
return 0;
}
+#endif
/*
* It reads ICR and sets flag (IXGBE_EICR_LSC) for the link_update.
@@ -3133,7 +3149,9 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw =
IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+#ifdef RTE_NEXT_ABI
uint32_t intr_vector = 0;
+#endif
struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
int err, mask = 0;
@@ -3166,6 +3184,7 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
ixgbevf_dev_rxtx_start(dev);
+#ifdef RTE_NEXT_ABI
/* check and configure queue intr-vector mapping */
if (dev->data->dev_conf.intr_conf.rxq != 0)
intr_vector = dev->data->nb_rx_queues;
@@ -3183,7 +3202,7 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
return -ENOMEM;
}
}
-
+#endif
ixgbevf_configure_msix(dev);
if (dev->data->dev_conf.intr_conf.lsc != 0) {
@@ -3229,19 +3248,23 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)
/* disable intr eventfd mapping */
rte_intr_disable(intr_handle);
+#ifdef RTE_NEXT_ABI
/* Clean datapath event and queue/vec mapping */
rte_intr_efd_disable(intr_handle);
if (intr_handle->intr_vec != NULL) {
rte_free(intr_handle->intr_vec);
intr_handle->intr_vec = NULL;
}
+#endif
}
static void
ixgbevf_dev_close(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+#ifdef RTE_NEXT_ABI
struct rte_pci_device *pci_dev;
+#endif
PMD_INIT_FUNC_TRACE();
@@ -3252,11 +3275,13 @@ ixgbevf_dev_close(struct rte_eth_dev *dev)
/* reprogram the RAR[0] in case user changed it. */
ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
+#ifdef RTE_NEXT_ABI
pci_dev = dev->pci_dev;
if (pci_dev->intr_handle.intr_vec) {
rte_free(pci_dev->intr_handle.intr_vec);
pci_dev->intr_handle.intr_vec = NULL;
}
+#endif
}
static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
@@ -3840,6 +3865,7 @@ ixgbe_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
return 0;
}
+#ifdef RTE_NEXT_ABI
static void
ixgbevf_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
uint8_t queue, uint8_t msix_vector)
@@ -3908,21 +3934,25 @@ ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
}
}
}
+#endif
static void
ixgbevf_configure_msix(struct rte_eth_dev *dev)
{
+ struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+#ifdef RTE_NEXT_ABI
struct ixgbe_hw *hw =
IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
uint32_t q_idx;
uint32_t vector_idx = 0;
+#endif
/* won't configure msix register if no mapping is done
* between intr vector and event fd */
if (!rte_intr_dp_is_en(intr_handle))
return;
+#ifdef RTE_NEXT_ABI
/* Configure all RX queues of VF */
for (q_idx = 0; q_idx < dev->data->nb_rx_queues; q_idx++) {
/* Force all queue use vector 0,
@@ -3933,6 +3963,7 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
/* Configure VF Rx queue ivar */
ixgbevf_set_ivar_map(hw, -1, 1, vector_idx);
+#endif
}
/**
@@ -3943,18 +3974,21 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
static void
ixgbe_configure_msix(struct rte_eth_dev *dev)
{
+ struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
+#ifdef RTE_NEXT_ABI
struct ixgbe_hw *hw =
IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
uint32_t queue_id, vec = 0;
uint32_t mask;
uint32_t gpie;
+#endif
/* won't configure msix register if no mapping is done
* between intr vector and event fd */
if (!rte_intr_dp_is_en(intr_handle))
return;
+#ifdef RTE_NEXT_ABI
/* setup GPIE for MSI-x mode */
gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
@@ -4006,6 +4040,7 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
IXGBE_EIMS_LSC);
IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
+#endif
}
static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index bae36f7..7f57491 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -239,7 +239,6 @@ static struct rte_eth_conf port_conf = {
},
.intr_conf = {
.lsc = 1,
- .rxq = 1, /**< rxq interrupt feature enabled */
},
};
@@ -889,7 +888,7 @@ main_loop(__attribute__((unused)) void *dummy)
}
/* add into event wait list */
- if (port_conf.intr_conf.rxq && event_register(qconf) == 0)
+ if (event_register(qconf) == 0)
intr_en = 1;
else
RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n");
diff --git a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h
index ba4640a..a730d89 100644
--- a/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h
+++ b/lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h
@@ -51,9 +51,16 @@ enum rte_intr_handle_type {
struct rte_intr_handle {
int fd; /**< file descriptor */
enum rte_intr_handle_type type; /**< handle type */
+#ifdef RTE_NEXT_ABI
+ /**
+ * RTE_NEXT_ABI will be removed from v2.2.
+ * It's only used to avoid ABI(unannounced) broken in v2.1.
+ * Make sure being aware of the impact before turning on the feature.
+ */
int max_intr; /**< max interrupt requested */
uint32_t nb_efd; /**< number of available efds */
int *intr_vec; /**< intr vector number array */
+#endif
};
/**
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index d7a5403..291d5ab 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -290,18 +290,26 @@ vfio_enable_msix(struct rte_intr_handle *intr_handle) {
irq_set = (struct vfio_irq_set *) irq_set_buf;
irq_set->argsz = len;
+#ifdef RTE_NEXT_ABI
if (!intr_handle->max_intr)
intr_handle->max_intr = 1;
else if (intr_handle->max_intr > RTE_MAX_RXTX_INTR_VEC_ID)
intr_handle->max_intr = RTE_MAX_RXTX_INTR_VEC_ID + 1;
irq_set->count = intr_handle->max_intr;
+#else
+ irq_set->count = 1;
+#endif
irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
irq_set->start = 0;
fd_ptr = (int *) &irq_set->data;
+#ifdef RTE_NEXT_ABI
memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds));
fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd;
+#else
+ fd_ptr[0] = intr_handle->fd;
+#endif
ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
@@ -876,6 +884,7 @@ rte_eal_intr_init(void)
return -ret;
}
+#ifdef RTE_NEXT_ABI
static void
eal_intr_proc_rxtx_intr(int fd, const struct rte_intr_handle *intr_handle)
{
@@ -918,6 +927,7 @@ eal_intr_proc_rxtx_intr(int fd, const struct rte_intr_handle *intr_handle)
return;
} while (1);
}
+#endif
static int
eal_epoll_process_event(struct epoll_event *evs, unsigned int n,
@@ -1056,6 +1066,7 @@ rte_epoll_ctl(int epfd, int op, int fd,
return 0;
}
+#ifdef RTE_NEXT_ABI
int
rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd,
int op, unsigned int vec, void *data)
@@ -1168,3 +1179,4 @@ rte_intr_efd_disable(struct rte_intr_handle *intr_handle)
intr_handle->nb_efd = 0;
intr_handle->max_intr = 0;
}
+#endif
diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h
index 912cc50..e46e65e 100644
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h
+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h
@@ -38,6 +38,10 @@
#ifndef _RTE_LINUXAPP_INTERRUPTS_H_
#define _RTE_LINUXAPP_INTERRUPTS_H_
+#ifndef RTE_NEXT_ABI
+#include <rte_common.h>
+#endif
+
#define RTE_MAX_RXTX_INTR_VEC_ID 32
enum rte_intr_handle_type {
@@ -86,12 +90,19 @@ struct rte_intr_handle {
};
int fd; /**< interrupt event file descriptor */
enum rte_intr_handle_type type; /**< handle type */
+#ifdef RTE_NEXT_ABI
+ /**
+ * RTE_NEXT_ABI will be removed from v2.2.
+ * It's only used to avoid ABI(unannounced) broken in v2.1.
+ * Make sure being aware of the impact before turning on the feature.
+ */
uint32_t max_intr; /**< max interrupt requested */
uint32_t nb_efd; /**< number of available efds */
int efds[RTE_MAX_RXTX_INTR_VEC_ID]; /**< intr vectors/efds mapping */
struct rte_epoll_event elist[RTE_MAX_RXTX_INTR_VEC_ID];
/**< intr vector epoll event */
int *intr_vec; /**< intr vector number array */
+#endif
};
#define RTE_EPOLL_PER_THREAD -1 /**< to hint using per thread epfd */
@@ -162,9 +173,23 @@ rte_intr_tls_epfd(void);
* - On success, zero.
* - On failure, a negative value.
*/
-int
+#ifdef RTE_NEXT_ABI
+extern int
rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
int epfd, int op, unsigned int vec, void *data);
+#else
+static inline int
+rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
+ int epfd, int op, unsigned int vec, void *data)
+{
+ RTE_SET_USED(intr_handle);
+ RTE_SET_USED(epfd);
+ RTE_SET_USED(op);
+ RTE_SET_USED(vec);
+ RTE_SET_USED(data);
+ return -ENOTSUP;
+}
+#endif
/**
* It enables the fastpath event fds if it's necessary.
@@ -179,8 +204,18 @@ rte_intr_rx_ctl(struct rte_intr_handle *intr_handle,
* - On success, zero.
* - On failure, a negative value.
*/
-int
+#ifdef RTE_NEXT_ABI
+extern int
rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd);
+#else
+static inline int
+rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
+{
+ RTE_SET_USED(intr_handle);
+ RTE_SET_USED(nb_efd);
+ return 0;
+}
+#endif
/**
* It disable the fastpath event fds.
@@ -189,8 +224,17 @@ rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd);
* @param intr_handle
* Pointer to the interrupt handle.
*/
-void
+#ifdef RTE_NEXT_ABI
+extern void
rte_intr_efd_disable(struct rte_intr_handle *intr_handle);
+#else
+static inline void
+rte_intr_efd_disable(struct rte_intr_handle *intr_handle)
+{
+ RTE_SET_USED(intr_handle);
+ return;
+}
+#endif
/**
* The fastpath interrupt is enabled or not.
@@ -198,11 +242,20 @@ rte_intr_efd_disable(struct rte_intr_handle *intr_handle);
* @param intr_handle
* Pointer to the interrupt handle.
*/
+#ifdef RTE_NEXT_ABI
static inline int
rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
{
return !(!intr_handle->nb_efd);
}
+#else
+static inline int
+rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
+{
+ RTE_SET_USED(intr_handle);
+ return 0;
+}
+#endif
/**
* The interrupt handle instance allows other cause or not.
@@ -211,10 +264,19 @@ rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
* @param intr_handle
* Pointer to the interrupt handle.
*/
+#ifdef RTE_NEXT_ABI
static inline int
rte_intr_allow_others(struct rte_intr_handle *intr_handle)
{
return !!(intr_handle->max_intr - intr_handle->nb_efd);
}
+#else
+static inline int
+rte_intr_allow_others(struct rte_intr_handle *intr_handle)
+{
+ RTE_SET_USED(intr_handle);
+ return 1;
+}
+#endif
#endif /* _RTE_LINUXAPP_INTERRUPTS_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index d149f12..4d4e456 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3281,6 +3281,7 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
}
+#ifdef RTE_NEXT_ABI
int
rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
{
@@ -3352,6 +3353,7 @@ rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
return 0;
}
+#endif
int
rte_eth_dev_rx_intr_enable(uint8_t port_id,
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index efa246f..8d8b641 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -830,8 +830,10 @@ struct rte_eth_fdir {
struct rte_intr_conf {
/** enable/disable lsc interrupt. 0 (default) - disable, 1 enable */
uint16_t lsc;
+#ifdef RTE_NEXT_ABI
/** enable/disable rxq interrupt. 0 (default) - disable, 1 enable */
uint16_t rxq;
+#endif
};
/**
@@ -2948,8 +2950,20 @@ int rte_eth_dev_rx_intr_disable(uint8_t port_id,
* - On success, zero.
* - On failure, a negative value.
*/
-int
+#ifdef RTE_NEXT_ABI
+extern int
rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data);
+#else
+static inline int
+rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
+{
+ RTE_SET_USED(port_id);
+ RTE_SET_USED(epfd);
+ RTE_SET_USED(op);
+ RTE_SET_USED(data);
+ return -1;
+}
+#endif
/**
* RX Interrupt control per queue.
@@ -2972,9 +2986,23 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data);
* - On success, zero.
* - On failure, a negative value.
*/
-int
+#ifdef RTE_NEXT_ABI
+extern int
rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
int epfd, int op, void *data);
+#else
+static inline int
+rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
+ int epfd, int op, void *data)
+{
+ RTE_SET_USED(port_id);
+ RTE_SET_USED(queue_id);
+ RTE_SET_USED(epfd);
+ RTE_SET_USED(op);
+ RTE_SET_USED(data);
+ return -1;
+}
+#endif
/**
* Turn on the LED on the Ethernet device.
--
1.8.1.4
^ permalink raw reply [relevance 10%]
* [dpdk-dev] [PATCH v13 10/14] ethdev: add rx intr enable, disable and ctl functions
2015-06-19 4:00 4% ` [dpdk-dev] [PATCH v13 " Cunming Liang
@ 2015-06-19 4:00 2% ` Cunming Liang
2015-06-19 4:00 10% ` [dpdk-dev] [PATCH v13 14/14] abi: fix v2.1 abi broken issue Cunming Liang
1 sibling, 0 replies; 200+ results
From: Cunming Liang @ 2015-06-19 4:00 UTC (permalink / raw)
To: dev; +Cc: shemming, liang-min.wang
The patch adds two dev_ops functions to enable and disable rx queue interrupts.
In addtion, it adds rte_eth_dev_rx_intr_ctl/rx_intr_q to support per port or per queue rx intr event set.
Signed-off-by: Danny Zhou <danny.zhou@intel.com>
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
v13 changes
- version map cleanup for v2.1
v9 changes
- remove unnecessary check after rte_eth_dev_is_valid_port.
the same as http://www.dpdk.org/dev/patchwork/patch/4784
v8 changes
- add addtion check for EEXIT
v7 changes
- remove rx_intr_vec_get
- add rx_intr_ctl and rx_intr_ctl_q
v6 changes
- add rx_intr_vec_get to retrieve the vector num of the queue.
v5 changes
- Rebase the patchset onto the HEAD
v4 changes
- Export interrupt enable/disable functions for shared libraries
- Put new functions at the end of eth_dev_ops to avoid breaking ABI
v3 changes
- Add return value for interrupt enable/disable functions
lib/librte_ether/rte_ethdev.c | 107 +++++++++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 104 ++++++++++++++++++++++++++++++++
lib/librte_ether/rte_ether_version.map | 4 ++
3 files changed, 215 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e13fde5..d149f12 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3280,6 +3280,113 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
}
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
}
+
+int
+rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
+{
+ uint32_t vec;
+ struct rte_eth_dev *dev;
+ struct rte_intr_handle *intr_handle;
+ uint16_t qid;
+ int rc;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%u\n", port_id);
+ return -ENODEV;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ intr_handle = &dev->pci_dev->intr_handle;
+ if (!intr_handle->intr_vec) {
+ PMD_DEBUG_TRACE("RX Intr vector unset\n");
+ return -EPERM;
+ }
+
+ for (qid = 0; qid < dev->data->nb_rx_queues; qid++) {
+ vec = intr_handle->intr_vec[qid];
+ rc = rte_intr_rx_ctl(intr_handle, epfd, op, vec, data);
+ if (rc && rc != -EEXIST) {
+ PMD_DEBUG_TRACE("p %u q %u rx ctl error"
+ " op %d epfd %d vec %u\n",
+ port_id, qid, op, epfd, vec);
+ }
+ }
+
+ return 0;
+}
+
+int
+rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
+ int epfd, int op, void *data)
+{
+ uint32_t vec;
+ struct rte_eth_dev *dev;
+ struct rte_intr_handle *intr_handle;
+ int rc;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%u\n", port_id);
+ return -ENODEV;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ if (queue_id >= dev->data->nb_rx_queues) {
+ PMD_DEBUG_TRACE("Invalid RX queue_id=%u\n", queue_id);
+ return -EINVAL;
+ }
+
+ intr_handle = &dev->pci_dev->intr_handle;
+ if (!intr_handle->intr_vec) {
+ PMD_DEBUG_TRACE("RX Intr vector unset\n");
+ return -EPERM;
+ }
+
+ vec = intr_handle->intr_vec[queue_id];
+ rc = rte_intr_rx_ctl(intr_handle, epfd, op, vec, data);
+ if (rc && rc != -EEXIST) {
+ PMD_DEBUG_TRACE("p %u q %u rx ctl error"
+ " op %d epfd %d vec %u\n",
+ port_id, queue_id, op, epfd, vec);
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+rte_eth_dev_rx_intr_enable(uint8_t port_id,
+ uint16_t queue_id)
+{
+ struct rte_eth_dev *dev;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -ENODEV;
+ }
+
+ dev = &rte_eth_devices[port_id];
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_intr_enable, -ENOTSUP);
+ return (*dev->dev_ops->rx_queue_intr_enable)(dev, queue_id);
+}
+
+int
+rte_eth_dev_rx_intr_disable(uint8_t port_id,
+ uint16_t queue_id)
+{
+ struct rte_eth_dev *dev;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -ENODEV;
+ }
+
+ dev = &rte_eth_devices[port_id];
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_intr_disable, -ENOTSUP);
+ return (*dev->dev_ops->rx_queue_intr_disable)(dev, queue_id);
+}
+
#ifdef RTE_NIC_BYPASS
int rte_eth_dev_bypass_init(uint8_t port_id)
{
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 04c192d..efa246f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -830,6 +830,8 @@ struct rte_eth_fdir {
struct rte_intr_conf {
/** enable/disable lsc interrupt. 0 (default) - disable, 1 enable */
uint16_t lsc;
+ /** enable/disable rxq interrupt. 0 (default) - disable, 1 enable */
+ uint16_t rxq;
};
/**
@@ -1035,6 +1037,14 @@ typedef int (*eth_tx_queue_setup_t)(struct rte_eth_dev *dev,
const struct rte_eth_txconf *tx_conf);
/**< @internal Setup a transmit queue of an Ethernet device. */
+typedef int (*eth_rx_enable_intr_t)(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id);
+/**< @internal Enable interrupt of a receive queue of an Ethernet device. */
+
+typedef int (*eth_rx_disable_intr_t)(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id);
+/**< @internal Disable interrupt of a receive queue of an Ethernet device. */
+
typedef void (*eth_queue_release_t)(void *queue);
/**< @internal Release memory resources allocated by given RX/TX queue. */
@@ -1391,6 +1401,10 @@ struct eth_dev_ops {
rss_hash_conf_get_t rss_hash_conf_get;
eth_filter_ctrl_t filter_ctrl; /**< common filter control*/
eth_set_mc_addr_list_t set_mc_addr_list; /**< set list of mcast addrs */
+
+ /** Enable/disable Rx queue interrupt. */
+ eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
+ eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt.*/
};
/**
@@ -2873,6 +2887,96 @@ void _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
enum rte_eth_event_type event);
/**
+ * When there is no rx packet coming in Rx Queue for a long time, we can
+ * sleep lcore related to RX Queue for power saving, and enable rx interrupt
+ * to be triggered when rx packect arrives.
+ *
+ * The rte_eth_dev_rx_intr_enable() function enables rx queue
+ * interrupt on specific rx queue of a port.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The index of the receive queue from which to retrieve input packets.
+ * The value must be in the range [0, nb_rx_queue - 1] previously supplied
+ * to rte_eth_dev_configure().
+ * @return
+ * - (0) if successful.
+ * - (-ENOTSUP) if underlying hardware OR driver doesn't support
+ * that operation.
+ * - (-ENODEV) if *port_id* invalid.
+ */
+int rte_eth_dev_rx_intr_enable(uint8_t port_id,
+ uint16_t queue_id);
+
+/**
+ * When lcore wakes up from rx interrupt indicating packet coming, disable rx
+ * interrupt and returns to polling mode.
+ *
+ * The rte_eth_dev_rx_intr_disable() function disables rx queue
+ * interrupt on specific rx queue of a port.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The index of the receive queue from which to retrieve input packets.
+ * The value must be in the range [0, nb_rx_queue - 1] previously supplied
+ * to rte_eth_dev_configure().
+ * @return
+ * - (0) if successful.
+ * - (-ENOTSUP) if underlying hardware OR driver doesn't support
+ * that operation.
+ * - (-ENODEV) if *port_id* invalid.
+ */
+int rte_eth_dev_rx_intr_disable(uint8_t port_id,
+ uint16_t queue_id);
+
+/**
+ * RX Interrupt control per port.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param epfd
+ * Epoll instance fd which the intr vector associated to.
+ * Using RTE_EPOLL_PER_THREAD allows to use per thread epoll instance.
+ * @param op
+ * The operation be performed for the vector.
+ * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}.
+ * @param data
+ * User raw data.
+ * @return
+ * - On success, zero.
+ * - On failure, a negative value.
+ */
+int
+rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data);
+
+/**
+ * RX Interrupt control per queue.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The index of the receive queue from which to retrieve input packets.
+ * The value must be in the range [0, nb_rx_queue - 1] previously supplied
+ * to rte_eth_dev_configure().
+ * @param epfd
+ * Epoll instance fd which the intr vector associated to.
+ * Using RTE_EPOLL_PER_THREAD allows to use per thread epoll instance.
+ * @param op
+ * The operation be performed for the vector.
+ * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}.
+ * @param data
+ * User raw data.
+ * @return
+ * - On success, zero.
+ * - On failure, a negative value.
+ */
+int
+rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
+ int epfd, int op, void *data);
+
+/**
* Turn on the LED on the Ethernet device.
* This function turns on the LED on the Ethernet device.
*
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 012a82e..3981b7b 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -109,6 +109,10 @@ DPDK_2.0 {
DPDK_2.1 {
global:
+ rte_eth_dev_rx_intr_ctl;
+ rte_eth_dev_rx_intr_ctl_q;
+ rte_eth_dev_rx_intr_disable;
+ rte_eth_dev_rx_intr_enable;
rte_eth_dev_set_mc_addr_list;
local: *;
--
1.8.1.4
^ permalink raw reply [relevance 2%]
* [dpdk-dev] [PATCH v13 00/14] Interrupt mode PMD
@ 2015-06-19 4:00 4% ` Cunming Liang
2015-06-19 4:00 2% ` [dpdk-dev] [PATCH v13 10/14] ethdev: add rx intr enable, disable and ctl functions Cunming Liang
2015-06-19 4:00 10% ` [dpdk-dev] [PATCH v13 14/14] abi: fix v2.1 abi broken issue Cunming Liang
0 siblings, 2 replies; 200+ results
From: Cunming Liang @ 2015-06-19 4:00 UTC (permalink / raw)
To: dev; +Cc: shemming, liang-min.wang
v13 changes
- version map cleanup for v2.1
- replace RTE_EAL_RX_INTR by RTE_NEXT_ABI for ABI compatibility
Patch series v12
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Danny Zhou <danny.zhou@intel.com>
v12 changes
- bsd cleanup for unused variable warning
- fix awkward line split in debug message
v11 changes
- typo cleanup and check kernel style
v10 changes
- code rework to return actual error code
- bug fix for lsc when using uio_pci_generic
v9 changes
- code rework to fix open comment
- bug fix for igb lsc when both lsc and rxq are enabled in vfio-msix
- new patch to turn off the feature by default so as to avoid v2.1 abi broken
v8 changes
- remove condition check for only vfio-msix
- add multiplex intr support when only one intr vector allowed
- lsc and rxq interrupt runtime enable decision
- add safe event delete while the event wakeup execution happens
v7 changes
- decouple epoll event and intr operation
- add condition check in the case intr vector is disabled
- renaming some APIs
v6 changes
- split rte_intr_wait_rx_pkt into two APIs 'wait' and 'set'.
- rewrite rte_intr_rx_wait/rte_intr_rx_set.
- using vector number instead of queue_id as interrupt API params.
- patch reorder and split.
v5 changes
- Rebase the patchset onto the HEAD
- Isolate ethdev from EAL for new-added wait-for-rx interrupt function
- Export wait-for-rx interrupt function for shared libraries
- Split-off a new patch file for changed struct rte_intr_handle that
other patches depend on, to avoid breaking git bisect
- Change sample applicaiton to accomodate EAL function spec change
accordingly
v4 changes
- Export interrupt enable/disable functions for shared libraries
- Adjust position of new-added structure fields and functions to
avoid breaking ABI
v3 changes
- Add return value for interrupt enable/disable functions
- Move spinlok from PMD to L3fwd-power
- Remove unnecessary variables in e1000_mac_info
- Fix miscelleous review comments
v2 changes
- Fix compilation issue in Makefile for missed header file.
- Consolidate internal and community review comments of v1 patch set.
The patch series introduce low-latency one-shot rx interrupt into DPDK with
polling and interrupt mode switch control example.
DPDK userspace interrupt notification and handling mechanism is based on UIO
with below limitation:
1) It is designed to handle LSC interrupt only with inefficient suspended
pthread wakeup procedure (e.g. UIO wakes up LSC interrupt handling thread
which then wakes up DPDK polling thread). In this way, it introduces
non-deterministic wakeup latency for DPDK polling thread as well as packet
latency if it is used to handle Rx interrupt.
2) UIO only supports a single interrupt vector which has to been shared by
LSC interrupt and interrupts assigned to dedicated rx queues.
This patchset includes below features:
1) Enable one-shot rx queue interrupt in ixgbe PMD(PF & VF) and igb PMD(PF only).
2) Build on top of the VFIO mechanism instead of UIO, so it could support
up to 64 interrupt vectors for rx queue interrupts.
3) Have 1 DPDK polling thread handle per Rx queue interrupt with a dedicated
VFIO eventfd, which eliminates non-deterministic pthread wakeup latency in
user space.
4) Demonstrate interrupts control APIs and userspace NAIP-like polling/interrupt
switch algorithms in L3fwd-power example.
Known limitations:
1) It does not work for UIO due to a single interrupt eventfd shared by LSC
and rx queue interrupt handlers causes a mess. [FIXED]
2) LSC interrupt is not supported by VF driver, so it is by default disabled
in L3fwd-power now. Feel free to turn in on if you want to support both LSC
and rx queue interrupts on a PF.
Cunming Liang (14):
eal/linux: add interrupt vectors support in intr_handle
eal/linux: add rte_epoll_wait/ctl support
eal/linux: add API to set rx interrupt event monitor
eal/linux: fix comments typo on vfio msi
eal/linux: add interrupt vectors handling on VFIO
eal/linux: standalone intr event fd create support
eal/linux: fix lsc read error in uio_pci_generic
eal/bsd: dummy for new intr definition
eal/bsd: fix inappropriate linuxapp referred in bsd
ethdev: add rx intr enable, disable and ctl functions
ixgbe: enable rx queue interrupts for both PF and VF
igb: enable rx queue interrupts for PF
l3fwd-power: enable one-shot rx interrupt and polling/interrupt mode
switch
abi: fix v2.1 abi broken issue
drivers/net/e1000/igb_ethdev.c | 311 ++++++++++--
drivers/net/ixgbe/ixgbe_ethdev.c | 519 ++++++++++++++++++++-
drivers/net/ixgbe/ixgbe_ethdev.h | 4 +
examples/l3fwd-power/main.c | 202 ++++++--
lib/librte_eal/bsdapp/eal/eal_interrupts.c | 30 ++
.../bsdapp/eal/include/exec-env/rte_interrupts.h | 91 +++-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 12 +
lib/librte_eal/linuxapp/eal/eal_interrupts.c | 362 ++++++++++++--
.../linuxapp/eal/include/exec-env/rte_interrupts.h | 219 +++++++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 15 +
lib/librte_ether/rte_ethdev.c | 109 +++++
lib/librte_ether/rte_ethdev.h | 132 ++++++
lib/librte_ether/rte_ether_version.map | 4 +
13 files changed, 1883 insertions(+), 127 deletions(-)
--
1.8.1.4
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v3 2/9] lib_vhost: Support multiple queues in virtio dev
2015-06-18 13:34 3% ` Flavio Leitner
@ 2015-06-19 1:17 3% ` Ouyang, Changchun
0 siblings, 0 replies; 200+ results
From: Ouyang, Changchun @ 2015-06-19 1:17 UTC (permalink / raw)
To: Flavio Leitner; +Cc: dev
> -----Original Message-----
> From: Flavio Leitner [mailto:fbl@sysclose.org]
> Sent: Thursday, June 18, 2015 9:34 PM
> To: Ouyang, Changchun
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 2/9] lib_vhost: Support multiple queues in
> virtio dev
>
> On Mon, Jun 15, 2015 at 03:56:39PM +0800, Ouyang Changchun wrote:
> > Each virtio device could have multiple queues, say 2 or 4, at most 8.
> > Enabling this feature allows virtio device/port on guest has the
> > ability to use different vCPU to receive/transmit packets from/to each
> queue.
> >
> > In multiple queues mode, virtio device readiness means all queues of
> > this virtio device are ready, cleanup/destroy a virtio device also
> > requires clearing all queues belong to it.
> >
> > Changes in v3:
> > - fix coding style
> > - check virtqueue idx validity
> >
> > Changes in v2:
> > - remove the q_num_set api
> > - add the qp_num_get api
> > - determine the queue pair num from qemu message
> > - rework for reset owner message handler
> > - dynamically alloc mem for dev virtqueue
> > - queue pair num could be 0x8000
> > - fix checkpatch errors
> >
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > ---
> > lib/librte_vhost/rte_virtio_net.h | 10 +-
> > lib/librte_vhost/vhost-net.h | 1 +
> > lib/librte_vhost/vhost_rxtx.c | 49 +++++---
> > lib/librte_vhost/vhost_user/vhost-net-user.c | 4 +-
> > lib/librte_vhost/vhost_user/virtio-net-user.c | 76 +++++++++---
> > lib/librte_vhost/vhost_user/virtio-net-user.h | 2 +
> > lib/librte_vhost/virtio-net.c | 161 +++++++++++++++++---------
> > 7 files changed, 216 insertions(+), 87 deletions(-)
> >
> > diff --git a/lib/librte_vhost/rte_virtio_net.h
> > b/lib/librte_vhost/rte_virtio_net.h
> > index 5d38185..873be3e 100644
> > --- a/lib/librte_vhost/rte_virtio_net.h
> > +++ b/lib/librte_vhost/rte_virtio_net.h
> > @@ -59,7 +59,6 @@ struct rte_mbuf;
> > /* Backend value set by guest. */
> > #define VIRTIO_DEV_STOPPED -1
> >
> > -
> > /* Enum for virtqueue management. */
> > enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
> >
> > @@ -96,13 +95,14 @@ struct vhost_virtqueue {
> > * Device structure contains all configuration information relating to the
> device.
> > */
> > struct virtio_net {
> > - struct vhost_virtqueue *virtqueue[VIRTIO_QNUM]; /**< Contains
> all virtqueue information. */
> > struct virtio_memory *mem; /**< QEMU memory and
> memory region information. */
> > + struct vhost_virtqueue **virtqueue; /**< Contains all virtqueue
> information. */
> > uint64_t features; /**< Negotiated feature set.
> */
> > uint64_t device_fh; /**< device identifier. */
> > uint32_t flags; /**< Device flags. Only used
> to check if device is running on data core. */
> > #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
> > char ifname[IF_NAME_SZ]; /**< Name of the tap
> device or socket path. */
> > + uint32_t num_virt_queues;
> > void *priv; /**< private context */
> > } __rte_cache_aligned;
>
>
> As already pointed out, this breaks ABI.
> Do you have a plan for that or are you pushing this for dpdk 2.2?
Yes, I think it will be enabled in 2.2.
I have already sent out the abi announce a few days ago.
>
>
> > @@ -220,4 +220,10 @@ uint16_t rte_vhost_enqueue_burst(struct
> > virtio_net *dev, uint16_t queue_id, uint16_t
> rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,
> > struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t
> > count);
> >
> > +/**
> > + * This function get the queue pair number of one vhost device.
> > + * @return
> > + * num of queue pair of specified virtio device.
> > + */
> > +uint16_t rte_vhost_qp_num_get(struct virtio_net *dev);
>
> This needs to go to rte_vhost_version.map too.
Will update it.
Thanks
Changchun
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-18 16:55 8% ` O'Driscoll, Tim
@ 2015-06-18 21:13 4% ` Vincent JARDIN
2015-06-19 10:26 9% ` Neil Horman
1 sibling, 0 replies; 200+ results
From: Vincent JARDIN @ 2015-06-18 21:13 UTC (permalink / raw)
To: O'Driscoll, Tim, Thomas Monjalon; +Cc: dev
On 18/06/2015 18:55, O'Driscoll, Tim wrote:
> I like Olivier's proposal on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these changes instead of a separate option per patch set (seehttp://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we should rework the affected patch sets to use that approach for 2.1.
Do we have any other options to meet the short deadlines of 2.1?
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
` (2 preceding siblings ...)
2015-06-17 10:35 9% ` Neil Horman
@ 2015-06-18 16:55 8% ` O'Driscoll, Tim
2015-06-18 21:13 4% ` Vincent JARDIN
2015-06-19 10:26 9% ` Neil Horman
3 siblings, 2 replies; 200+ results
From: O'Driscoll, Tim @ 2015-06-18 16:55 UTC (permalink / raw)
To: Thomas Monjalon, dev
> -----Original Message-----
> From: announce [mailto:announce-bounces@dpdk.org] On Behalf Of Thomas
> Monjalon
> Sent: Wednesday, June 17, 2015 12:30 AM
> To: announce@dpdk.org
> Subject: [dpdk-announce] important design choices - statistics - ABI
>
> Hi all,
>
> During the development of the release 2.0, there was an agreement to
> keep
> ABI compatibility or to bring new ABI while keeping old one during one
> release.
> In case it's not possible to have this transition, the (exceptional)
> break
> should be acknowledged by several developers.
> http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
> There were some interesting discussions but not a lot of participants:
> http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus
> =8461
>
> During the current development cycle for the release 2.1, the ABI
> question
> arises many times in different threads.
> To add the hash key size field, it is proposed to use a struct padding
> gap:
> http://dpdk.org/ml/archives/dev/2015-June/019386.html
> To support the flow director for VF, there is no proposal yet:
> http://dpdk.org/ml/archives/dev/2015-June/019343.html
> To add the speed capability, it is proposed to break ABI in the release
> 2.2:
> http://dpdk.org/ml/archives/dev/2015-June/019225.html
> To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
> http://dpdk.org/ml/archives/dev/2015-June/019443.html
> To add the interrupt mode, it is proposed to add a build-time option
> CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking
> binary:
> http://dpdk.org/ml/archives/dev/2015-June/018947.html
> To add the packet type, there is a proposal to add a build-time option
> CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
> http://dpdk.org/ml/archives/dev/2015-June/019172.html
> We must also better document how to remove a deprecated ABI:
> http://dpdk.org/ml/archives/dev/2015-June/019465.html
> The ABI compatibility is a new constraint and we need to better
> understand
> what it means and how to proceed. Even the macros are not yet well
> documented:
> http://dpdk.org/ml/archives/dev/2015-June/019357.html
>
> Thanks for your attention and your participation in these important
> choices.
There's been some good discussion on the ABI policy in various responses to this email. I think we now need to reach a conclusion on how we're going to proceed for the 2.1 release. Then, we can have further discussion on the use of versioning or other methods for avoiding the problem in future.
For the 2.1 release, I think we should agree to make patches that change the ABI controllable via a compile-time option. I like Olivier's proposal on using a single option (CONFIG_RTE_NEXT_ABI) to control all of these changes instead of a separate option per patch set (see http://dpdk.org/ml/archives/dev/2015-June/019147.html), so I think we should rework the affected patch sets to use that approach for 2.1.
Tim
^ permalink raw reply [relevance 8%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 11:17 4% ` Bruce Richardson
@ 2015-06-18 16:32 4% ` Dumitrescu, Cristian
0 siblings, 0 replies; 200+ results
From: Dumitrescu, Cristian @ 2015-06-18 16:32 UTC (permalink / raw)
To: Richardson, Bruce, Matthew Hall; +Cc: dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bruce Richardson
> Sent: Wednesday, June 17, 2015 12:17 PM
> To: Matthew Hall
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-announce] important design choices -
> statistics - ABI
>
> On Tue, Jun 16, 2015 at 09:36:54PM -0700, Matthew Hall wrote:
> > On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> > > There were some debates about software statistics disabling.
> > > Should they be always on or possibly disabled when compiled?
> > > We need to take a decision shortly and discuss (or agree) this proposal:
> > > http://dpdk.org/ml/archives/dev/2015-June/019461.html
> >
> > This goes against the idea I have seen before that we should be moving
> toward
> > a distro-friendly approach where one copy of DPDK can be used by multiple
> apps
> > without having to rebuild it. It seems like it is also a bit ABI hostile
> > according to the below goals / discussions.
> >
> > Jemalloc is also very high-performance code and still manages to allow
> > enabling and disabling statistics at runtime. Are we sure it's impossible for
> > DPDK or just theorizing?
> >
>
> +1 to this. I think that any compile-time option to disable stats should only
> be used when we have a proven performance issue with just disabling them
> at runtime.
> I would assume that apps do not switch on or off stats multiple times per
> second,
> so any code branches to track stats or not would be entirely predictable in
> the
> code - since they always go one way. Therefore, when disabledi, we should
> be looking
> at a very minimal overhead per stat. If there are lots of checks for the same
> value in the one path, i.e. lots of stats in a hot path, hopefully the compiler
> will be smart enough to make the check just once. If not, we can always do
> that in the C code by duplicating the hotpath code for with or without stats
> cases -
> again selectable at runtime.
>
I see where you're coming from, but reality is you cannot guarantee that the few conditional branches in the library are going to be predicted correctly simply because the application and the other libraries used by the app have an unknown number of conditional branches themselves. For complex apps, the total number of conditional branches is large and the more there are, the lesser probability of such a branch being predicted correctly is. I agree that for test apps like l3fwd with just a few branches the probability to have library branches being predicted correctly is high, but for me is an incorrect proof point. The cost of ~14 cycles per branch misprediction is important for DPDK packet budgets.
Since we don't control the application, I am feeling very uncomfortable with generic statements about how application is likely to execute and the impact of library conditional branches over the application should be. To me, they sound like we are willing to take chances, and to me this is not the right decision. In my opinion, the right decision for a significant framework like DPDK is to keep all options open for the apps: keep counters always enabled, keep counters always disabled, keep counters enabled first and disabled later. I suggest we should move the focus from WHY arguments like: "I don't think anybody will ever need this this" to the HOW part of making sure that technical solution we pick is correct and keeps all options open.
I think stats are not always equivalent to incrementing a counter. In the guideline proposal, I am providing several examples of more complex statistics logic that is more than just inc one counter. As an extreme case, think about the case where the metric to compute requires complex math like prediction of next packet arrival time based on recent history, etc. When defining a policy, we should consider a broad spectrum of metrics, not just n_pkts_in.
> Also, there is also the case where the stats tracking itself is such low
> overhead
> that its not worth disabling. In that case, neither runtime nor compile-time
> disabling
> should need to be provided. For example, any library that is keeping a track
> of
> bursts of packets should not need to have that stat disable option - one
> increment
> or addition per burst of (32) packets is not going to seriously affect any app. :-
> )
>
> Regards,
> /Bruce
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
2015-06-18 15:06 0% ` Marc Sune
@ 2015-06-18 15:33 3% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-06-18 15:33 UTC (permalink / raw)
To: Marc Sune; +Cc: dev, Morten Brørup
2015-06-18 17:06, Marc Sune:
> On 18/06/15 16:43, Morten Brørup wrote:
> > Regarding the PHY speed ABI:
> >
> > 1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)
>
> Thomas was sending a similar comment and I agreed to do a unified speed
> bitmap for both capabilities and link negotiation/link info (v3, waiting
> for 2.2 merge window):
>
> http://dpdk.org/ml/archives/dev/2015-June/019207.html
It would be better to try merging it in 2.1 while keeping an ABI backward
compatibility.
> > 2. The auto-negotiation standard allows the PHY to announce (to its link
> > partner) any subset of its capabilities to its link partner. E.g. a
> > standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s
> > in both half and full duplex and 1 Gbit/s full duplex) can be configured
> > to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities
> > to its link partner. (Of course, more useful combinations are normally
> > announced, but the purpose of the example is to show that any combination
> > is possible.)
> >
> > The ABI for auto-negotiation should include options to select the list of
> > capabilities to announce to the link partner. The Linux PHY ABI only
> > allows forcing a selected speed and duplex (thereby disabling
> > auto-negotiation) or enabling auto-negotiation (thereby announcing all
> > possible speeds and duplex combinations the PHY is capable of). Don't make
> > the same mistake in DPDK.
>
> I see what you mean, and you are probably right. In any case this is for
> a separate patch, if we think it is a necessary feature to implement.
>
> Nevertheless, this makes me rethink about the proposal from Thomas about
> unifying _100_HD/_100_FD to 100M, because you will need this
> granularity, eventually. @Thomas: opinions?
I think Morten's advice is good.
Are we going to have half duplex links for PHY faster than 100M?
If not, we can manage them with a hackish define 100M_HD and a 100M
which implicitly means full duplex.
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
2015-06-18 14:43 5% [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Morten Brørup
@ 2015-06-18 15:06 0% ` Marc Sune
2015-06-18 15:33 3% ` Thomas Monjalon
0 siblings, 1 reply; 200+ results
From: Marc Sune @ 2015-06-18 15:06 UTC (permalink / raw)
To: dev, Thomas Monjalon
On 18/06/15 16:43, Morten Brørup wrote:
> Regarding the PHY speed ABI:
>
>
>
> 1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)
Thomas was sending a similar comment and I agreed to do a unified speed
bitmap for both capabilities and link negotiation/link info (v3, waiting
for 2.2 merge window):
http://dpdk.org/ml/archives/dev/2015-June/019207.html
>
>
>
> 2. The auto-negotiation standard allows the PHY to announce (to its link partner) any subset of its capabilities to its link partner. E.g. a standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s in both half and full duplex and 1 Gbit/s full duplex) can be configured to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities to its link partner. (Of course, more useful combinations are normally announced, but the purpose of the example is to show that any combination is possible.)
>
>
>
> The ABI for auto-negotiation should include options to select the list of capabilities to announce to the link partner. The Linux PHY ABI only allows forcing a selected speed and duplex (thereby disabling auto-negotiation) or enabling auto-negotiation (thereby announcing all possible speeds and duplex combinations the PHY is capable of). Don't make the same mistake in DPDK.
I see what you mean, and you are probably right. In any case this is for
a separate patch, if we think it is a necessary feature to implement.
Nevertheless, this makes me rethink about the proposal from Thomas about
unifying _100_HD/_100_FD to 100M, because you will need this
granularity, eventually. @Thomas: opinions?
Thanks
Marc
p.s. Please configure your email client to reply using "In-Reply-To:" to
allow clients and ML archives to use threading.
>
>
> PS: While working for Vitesse Semiconductors (an Ethernet chip company) a long time ago, I actually wrote the API for their line of Ethernet PHYs. So I have hands on experience in this area.
>
>
>
>
>
> Med venlig hilsen / kind regards
>
>
>
> Morten Brørup
>
> CTO
>
>
>
>
>
>
>
> SmartShare Systems A/S
>
> Tonsbakken 16-18
>
> DK-2740 Skovlunde
>
> Denmark
>
>
>
> Office +45 70 20 00 93
>
> Direct +45 89 93 50 22
>
> Mobile +45 25 40 82 12
>
>
>
> mb@smartsharesystems.com <mailto:mb@smartsharesystems.com>
>
> www.smartsharesystems.com <http://www.smartsharesystems.com/>
>
>
>
^ permalink raw reply [relevance 0%]
* [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info
@ 2015-06-18 14:43 5% Morten Brørup
2015-06-18 15:06 0% ` Marc Sune
0 siblings, 1 reply; 200+ results
From: Morten Brørup @ 2015-06-18 14:43 UTC (permalink / raw)
To: dev
Regarding the PHY speed ABI:
1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)
2. The auto-negotiation standard allows the PHY to announce (to its link partner) any subset of its capabilities to its link partner. E.g. a standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s in both half and full duplex and 1 Gbit/s full duplex) can be configured to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities to its link partner. (Of course, more useful combinations are normally announced, but the purpose of the example is to show that any combination is possible.)
The ABI for auto-negotiation should include options to select the list of capabilities to announce to the link partner. The Linux PHY ABI only allows forcing a selected speed and duplex (thereby disabling auto-negotiation) or enabling auto-negotiation (thereby announcing all possible speeds and duplex combinations the PHY is capable of). Don't make the same mistake in DPDK.
PS: While working for Vitesse Semiconductors (an Ethernet chip company) a long time ago, I actually wrote the API for their line of Ethernet PHYs. So I have hands on experience in this area.
Med venlig hilsen / kind regards
Morten Brørup
CTO
SmartShare Systems A/S
Tonsbakken 16-18
DK-2740 Skovlunde
Denmark
Office +45 70 20 00 93
Direct +45 89 93 50 22
Mobile +45 25 40 82 12
mb@smartsharesystems.com <mailto:mb@smartsharesystems.com>
www.smartsharesystems.com <http://www.smartsharesystems.com/>
^ permalink raw reply [relevance 5%]
* Re: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX queue information
2015-06-18 14:17 3% ` Ananyev, Konstantin
@ 2015-06-18 14:37 0% ` Walukiewicz, Miroslaw
0 siblings, 0 replies; 200+ results
From: Walukiewicz, Miroslaw @ 2015-06-18 14:37 UTC (permalink / raw)
To: Ananyev, Konstantin, dev
> -----Original Message-----
> From: Ananyev, Konstantin
> Sent: Thursday, June 18, 2015 4:17 PM
> To: Walukiewicz, Miroslaw; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX
> queue information
>
> Hi Mirek,
>
> > -----Original Message-----
> > From: Walukiewicz, Miroslaw
> > Sent: Thursday, June 18, 2015 2:31 PM
> > To: Ananyev, Konstantin; dev@dpdk.org
> > Subject: RE: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve
> RX/TX queue information
> >
> > Konstantin,
> >
> > Is there a possibility to read information about available space in NIC queue
> for TX.
>
> I suppose it is possible as some future addition.
> As I said in the commit message, I left some reserved space, so extra fields
> could be added to the structure without ABI breakage.
> For now, I just added some static/config information for the queue, but I think
> it is possible and plausible to have some runtime information too.
>
> >
> > It is quite easy to compute (or even available directly) and very useful
> especially for application sending multi-descriptor packets like
> > TCP TSO.
> >
> > Now there is no access to such information and the transmit packet function
> must be called to
> > be sure that there is available space.
>
> Hmm, as I said I was thinking about adding some RT information in future:
> number of free descriptors (from SW point of view), index of next descriptor
> to process by SW, etc.
> But my thought it would be use by some watchdog thread to collect
> statistics/detect stall, etc.
> I didn't intend it to be used by IO thread.
>
> I am not sure why do you need to call such function at RT?
> PMD wouldn't TX a packet, if there is not enough free TXDs for the whole
> packet.
> From other side upper layer, can't always calculate correctly how many TXD it
> would really need
> (context descriptors might be needed, etc).
> Plus, even if nb_tx_free==X, in reality it could be there much more free
> TXDs, and SW just need
> to process them (and would do that at next tx_burst() call.
> So, why just not:
> ...
> n = tx_burst(..., nb_tx);
> if (n < nb_tx) {requeue unsent of packets;}
> ?
>
The case is TCP TSO operation as I said.
I really use the that method proposed by you but it very expensive way.
The TX path in TCP is very complex and expensive.
It is desirable to create the TCP TSO segments that fits the space in queue to avoid re-queue of packets
making the TX path much more complex.
For ixgbe the TSO segments are up to 40 descriptors (max 64K of data) and making the TX queue full is just simple.
Having the possibility for reading number of descriptors available to send can improve TCP TX process in the way
that when there is no space in TX queue we can just not enter the complex TX path and spent time making more
useful job than re-queue.
Also It is easy to fit the TSO segment to available space in TX queue instead of sending always a large 64K TCP segments
and count on the result of tx_burst and re-queue in case of lack of space.
Mirek
> Konstantin
>
> >
> > Mirek
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Konstantin
> Ananyev
> > > Sent: Thursday, June 18, 2015 3:19 PM
> > > To: dev@dpdk.org
> > > Subject: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX
> > > queue information
> > >
> > > Add the ability for the upper layer to query RX/TX queue information.
> > > Right now supported for:
> > > ixgbe, i40e, e1000 PMDs.
> > >
> > > Konstantin Ananyev (5):
> > > ethdev: add new API to retrieve RX/TX queue information
> > > i40e: add support for eth_(rxq|txq)_info_get
> > > ixgbe: add support for eth_(rxq|txq)_info_get
> > > e1000: add support for eth_(rxq|txq)_info_get
> > > testpmd: add new command to display RX/TX queue information
> > >
> > > app/test-pmd/cmdline.c | 48 +++++++++++++++++++++++++
> > > app/test-pmd/config.c | 67
> > > ++++++++++++++++++++++++++++++++++
> > > app/test-pmd/testpmd.h | 2 ++
> > > drivers/net/e1000/e1000_ethdev.h | 12 +++++++
> > > drivers/net/e1000/em_ethdev.c | 2 ++
> > > drivers/net/e1000/em_rxtx.c | 38 ++++++++++++++++++++
> > > drivers/net/e1000/igb_ethdev.c | 4 +++
> > > drivers/net/e1000/igb_rxtx.c | 36 +++++++++++++++++++
> > > drivers/net/i40e/i40e_ethdev.c | 2 ++
> > > drivers/net/i40e/i40e_ethdev.h | 5 +++
> > > drivers/net/i40e/i40e_rxtx.c | 42 ++++++++++++++++++++++
> > > drivers/net/ixgbe/ixgbe_ethdev.c | 4 +++
> > > drivers/net/ixgbe/ixgbe_ethdev.h | 6 ++++
> > > drivers/net/ixgbe/ixgbe_rxtx.c | 42 ++++++++++++++++++++++
> > > lib/librte_ether/rte_ethdev.c | 54 ++++++++++++++++++++++++++++
> > > lib/librte_ether/rte_ethdev.h | 77
> > > +++++++++++++++++++++++++++++++++++++++-
> > > 16 files changed, 440 insertions(+), 1 deletion(-)
> > >
> > > --
> > > 1.8.5.3
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX queue information
@ 2015-06-18 14:17 3% ` Ananyev, Konstantin
2015-06-18 14:37 0% ` Walukiewicz, Miroslaw
0 siblings, 1 reply; 200+ results
From: Ananyev, Konstantin @ 2015-06-18 14:17 UTC (permalink / raw)
To: Walukiewicz, Miroslaw, dev
Hi Mirek,
> -----Original Message-----
> From: Walukiewicz, Miroslaw
> Sent: Thursday, June 18, 2015 2:31 PM
> To: Ananyev, Konstantin; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX queue information
>
> Konstantin,
>
> Is there a possibility to read information about available space in NIC queue for TX.
I suppose it is possible as some future addition.
As I said in the commit message, I left some reserved space, so extra fields could be added to the structure without ABI breakage.
For now, I just added some static/config information for the queue, but I think it is possible and plausible to have some runtime information too.
>
> It is quite easy to compute (or even available directly) and very useful especially for application sending multi-descriptor packets like
> TCP TSO.
>
> Now there is no access to such information and the transmit packet function must be called to
> be sure that there is available space.
Hmm, as I said I was thinking about adding some RT information in future:
number of free descriptors (from SW point of view), index of next descriptor to process by SW, etc.
But my thought it would be use by some watchdog thread to collect statistics/detect stall, etc.
I didn't intend it to be used by IO thread.
I am not sure why do you need to call such function at RT?
PMD wouldn't TX a packet, if there is not enough free TXDs for the whole packet.
>From other side upper layer, can't always calculate correctly how many TXD it would really need
(context descriptors might be needed, etc).
Plus, even if nb_tx_free==X, in reality it could be there much more free TXDs, and SW just need
to process them (and would do that at next tx_burst() call.
So, why just not:
...
n = tx_burst(..., nb_tx);
if (n < nb_tx) {requeue unsent of packets;}
?
Konstantin
>
> Mirek
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Konstantin Ananyev
> > Sent: Thursday, June 18, 2015 3:19 PM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX
> > queue information
> >
> > Add the ability for the upper layer to query RX/TX queue information.
> > Right now supported for:
> > ixgbe, i40e, e1000 PMDs.
> >
> > Konstantin Ananyev (5):
> > ethdev: add new API to retrieve RX/TX queue information
> > i40e: add support for eth_(rxq|txq)_info_get
> > ixgbe: add support for eth_(rxq|txq)_info_get
> > e1000: add support for eth_(rxq|txq)_info_get
> > testpmd: add new command to display RX/TX queue information
> >
> > app/test-pmd/cmdline.c | 48 +++++++++++++++++++++++++
> > app/test-pmd/config.c | 67
> > ++++++++++++++++++++++++++++++++++
> > app/test-pmd/testpmd.h | 2 ++
> > drivers/net/e1000/e1000_ethdev.h | 12 +++++++
> > drivers/net/e1000/em_ethdev.c | 2 ++
> > drivers/net/e1000/em_rxtx.c | 38 ++++++++++++++++++++
> > drivers/net/e1000/igb_ethdev.c | 4 +++
> > drivers/net/e1000/igb_rxtx.c | 36 +++++++++++++++++++
> > drivers/net/i40e/i40e_ethdev.c | 2 ++
> > drivers/net/i40e/i40e_ethdev.h | 5 +++
> > drivers/net/i40e/i40e_rxtx.c | 42 ++++++++++++++++++++++
> > drivers/net/ixgbe/ixgbe_ethdev.c | 4 +++
> > drivers/net/ixgbe/ixgbe_ethdev.h | 6 ++++
> > drivers/net/ixgbe/ixgbe_rxtx.c | 42 ++++++++++++++++++++++
> > lib/librte_ether/rte_ethdev.c | 54 ++++++++++++++++++++++++++++
> > lib/librte_ether/rte_ethdev.h | 77
> > +++++++++++++++++++++++++++++++++++++++-
> > 16 files changed, 440 insertions(+), 1 deletion(-)
> >
> > --
> > 1.8.5.3
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCHv2 0/5] ethdev: add new API to retrieve RX/TX queue information
2015-06-18 13:18 2% ` [dpdk-dev] [PATCHv2 1/5] " Konstantin Ananyev
@ 2015-06-18 13:58 3% ` Bruce Richardson
2 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2015-06-18 13:58 UTC (permalink / raw)
To: Konstantin Ananyev; +Cc: dev
On Thu, Jun 18, 2015 at 02:18:43PM +0100, Konstantin Ananyev wrote:
> Add the ability for the upper layer to query RX/TX queue information.
> Right now supported for:
> ixgbe, i40e, e1000 PMDs.
>
> Konstantin Ananyev (5):
> ethdev: add new API to retrieve RX/TX queue information
> i40e: add support for eth_(rxq|txq)_info_get
> ixgbe: add support for eth_(rxq|txq)_info_get
> e1000: add support for eth_(rxq|txq)_info_get
> testpmd: add new command to display RX/TX queue information
>
> app/test-pmd/cmdline.c | 48 +++++++++++++++++++++++++
> app/test-pmd/config.c | 67 ++++++++++++++++++++++++++++++++++
> app/test-pmd/testpmd.h | 2 ++
> drivers/net/e1000/e1000_ethdev.h | 12 +++++++
> drivers/net/e1000/em_ethdev.c | 2 ++
> drivers/net/e1000/em_rxtx.c | 38 ++++++++++++++++++++
> drivers/net/e1000/igb_ethdev.c | 4 +++
> drivers/net/e1000/igb_rxtx.c | 36 +++++++++++++++++++
> drivers/net/i40e/i40e_ethdev.c | 2 ++
> drivers/net/i40e/i40e_ethdev.h | 5 +++
> drivers/net/i40e/i40e_rxtx.c | 42 ++++++++++++++++++++++
> drivers/net/ixgbe/ixgbe_ethdev.c | 4 +++
> drivers/net/ixgbe/ixgbe_ethdev.h | 6 ++++
> drivers/net/ixgbe/ixgbe_rxtx.c | 42 ++++++++++++++++++++++
> lib/librte_ether/rte_ethdev.c | 54 ++++++++++++++++++++++++++++
> lib/librte_ether/rte_ethdev.h | 77 +++++++++++++++++++++++++++++++++++++++-
> 16 files changed, 440 insertions(+), 1 deletion(-)
>
> --
> 1.8.5.3
>
Series Acked-by: Bruce Richardson <bruce.richardson@intel.com>
BTW: I'm sure there are plenty of possible suggestions for extensions to these
functions, but rather than constantly doing new versions to keep adding things
in, can we get the base functionality applied and add in the new info later -
as separate patches? There is space in the structs for more info without
affecting the ABI.
Regards,
/Bruce
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [PATCH v3 2/9] lib_vhost: Support multiple queues in virtio dev
@ 2015-06-18 13:34 3% ` Flavio Leitner
2015-06-19 1:17 3% ` Ouyang, Changchun
0 siblings, 1 reply; 200+ results
From: Flavio Leitner @ 2015-06-18 13:34 UTC (permalink / raw)
To: Ouyang Changchun; +Cc: dev
On Mon, Jun 15, 2015 at 03:56:39PM +0800, Ouyang Changchun wrote:
> Each virtio device could have multiple queues, say 2 or 4, at most 8.
> Enabling this feature allows virtio device/port on guest has the ability to
> use different vCPU to receive/transmit packets from/to each queue.
>
> In multiple queues mode, virtio device readiness means all queues of
> this virtio device are ready, cleanup/destroy a virtio device also
> requires clearing all queues belong to it.
>
> Changes in v3:
> - fix coding style
> - check virtqueue idx validity
>
> Changes in v2:
> - remove the q_num_set api
> - add the qp_num_get api
> - determine the queue pair num from qemu message
> - rework for reset owner message handler
> - dynamically alloc mem for dev virtqueue
> - queue pair num could be 0x8000
> - fix checkpatch errors
>
> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> ---
> lib/librte_vhost/rte_virtio_net.h | 10 +-
> lib/librte_vhost/vhost-net.h | 1 +
> lib/librte_vhost/vhost_rxtx.c | 49 +++++---
> lib/librte_vhost/vhost_user/vhost-net-user.c | 4 +-
> lib/librte_vhost/vhost_user/virtio-net-user.c | 76 +++++++++---
> lib/librte_vhost/vhost_user/virtio-net-user.h | 2 +
> lib/librte_vhost/virtio-net.c | 161 +++++++++++++++++---------
> 7 files changed, 216 insertions(+), 87 deletions(-)
>
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index 5d38185..873be3e 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -59,7 +59,6 @@ struct rte_mbuf;
> /* Backend value set by guest. */
> #define VIRTIO_DEV_STOPPED -1
>
> -
> /* Enum for virtqueue management. */
> enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
>
> @@ -96,13 +95,14 @@ struct vhost_virtqueue {
> * Device structure contains all configuration information relating to the device.
> */
> struct virtio_net {
> - struct vhost_virtqueue *virtqueue[VIRTIO_QNUM]; /**< Contains all virtqueue information. */
> struct virtio_memory *mem; /**< QEMU memory and memory region information. */
> + struct vhost_virtqueue **virtqueue; /**< Contains all virtqueue information. */
> uint64_t features; /**< Negotiated feature set. */
> uint64_t device_fh; /**< device identifier. */
> uint32_t flags; /**< Device flags. Only used to check if device is running on data core. */
> #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
> char ifname[IF_NAME_SZ]; /**< Name of the tap device or socket path. */
> + uint32_t num_virt_queues;
> void *priv; /**< private context */
> } __rte_cache_aligned;
As already pointed out, this breaks ABI.
Do you have a plan for that or are you pushing this for dpdk 2.2?
> @@ -220,4 +220,10 @@ uint16_t rte_vhost_enqueue_burst(struct virtio_net *dev, uint16_t queue_id,
> uint16_t rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,
> struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
>
> +/**
> + * This function get the queue pair number of one vhost device.
> + * @return
> + * num of queue pair of specified virtio device.
> + */
> +uint16_t rte_vhost_qp_num_get(struct virtio_net *dev);
This needs to go to rte_vhost_version.map too.
fbl
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 11:17 4% ` Bruce Richardson
@ 2015-06-18 13:25 8% ` Dumitrescu, Cristian
2 siblings, 0 replies; 200+ results
From: Dumitrescu, Cristian @ 2015-06-18 13:25 UTC (permalink / raw)
To: Matthew Hall, dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Matthew Hall
> Sent: Wednesday, June 17, 2015 5:37 AM
> To: dev@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-announce] important design choices -
> statistics - ABI
>
> On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> > There were some debates about software statistics disabling.
> > Should they be always on or possibly disabled when compiled?
> > We need to take a decision shortly and discuss (or agree) this proposal:
> > http://dpdk.org/ml/archives/dev/2015-June/019461.html
>
> This goes against the idea I have seen before that we should be moving
> toward
> a distro-friendly approach where one copy of DPDK can be used by multiple
> apps
> without having to rebuild it. It seems like it is also a bit ABI hostile
> according to the below goals / discussions.
Matthew, thanks for your input. As Thomas also mentions, it would be good to first read the proposal on the guideline (http://dpdk.org/ml/archives/dev/2015-June/019461.html).
In the guideline proposal, we are addressing the topic of preventing the ABI changes due to library statistics support, it would be good to get your opinion on that, I am not sure you saw it. Given DPDK paramount focus on performance, I think probably provides the best solution for ABI compatibility in this case.
>
> Jemalloc is also very high-performance code and still manages to allow
> enabling and disabling statistics at runtime. Are we sure it's impossible for
> DPDK or just theorizing?
A performance improvement for one environment might still be an overkill for DPDK run-time environment.
Stats cannot be enabled/disabled at run-time without performance impact, as it typically requires testing a persistent flag for incrementing the stats counters, which requires a conditional branch instruction. Sometimes the branches are predicted correctly, sometimes not, and in this case the CPU pipeline needs to be flushed; typical branch misprediction cost is ~14 cycles, which is important given a packet budget of ~200 cycles.
When only a small number of branches are present in the (application + library) code, they are predicted correctly, so I am sure that for a simple test application like l3fw the cost of run-time enabled stats is not visible. The problem is that real applications are much more complex and they typically have a lot of conditional branches, out of which the library stats test is just one of them, so they cannot be all predicted correctly, hence the cost of stats run-time enablement becomes very much visible.
>
> > During the development of the release 2.0, there was an agreement to
> keep
> > ABI compatibility or to bring new ABI while keeping old one during one
> release.
> > In case it's not possible to have this transition, the (exceptional) break
> > should be acknowledged by several developers.
>
> Personally to me it seems more important to preserve the ABI on patch
> releases, like 2.X.Y going to 2.X.Z. But maybe I missed something?
>
> > During the current development cycle for the release 2.1, the ABI question
> > arises many times in different threads.
>
> Most but not all of these examples point to a different issue which
> sometimes
> happens in libraries... often seen as "old-style" versus "new-style" C library
> interface. For example, in old-style like libpcap there are a lot of structs,
> both opaque and non-opaque, which the caller must allocate in order to run
> libpcap.
>
> However new-style libraries such as libcurl usually just have init functions
> which initialize all the secret structs based on some defaults and some user
> parameters and hide the actual structs from the user. If you want to adjust
> some you call an adjuster function that modifies the actual secret struct
> contents, with some enum saying what field to adjust, and the new value
> you
> want it to have.
>
> If you want to keep a stable ABI for a non-stable library like DPDK, there's a
> good chance you must begin hiding all these weird device specific structs all
> over the DPDK from the user needing to directly allocate and modify them.
> Otherwise the ABI breaks everytime you have to add adjustments,
> extensions,
> modifications to all these obscure special features.
>
> Matthew.
^ permalink raw reply [relevance 8%]
* [dpdk-dev] [PATCHv2 1/5] ethdev: add new API to retrieve RX/TX queue information
@ 2015-06-18 13:18 2% ` Konstantin Ananyev
2015-06-18 13:58 3% ` Bruce Richardson
2 siblings, 0 replies; 200+ results
From: Konstantin Ananyev @ 2015-06-18 13:18 UTC (permalink / raw)
To: dev
Add the ability for the upper layer to query RX/TX queue information.
Add new structures:
struct rte_eth_rxq_info
struct rte_eth_txq_info
new functions:
rte_eth_rx_queue_info_get
rte_eth_tx_queue_info_get
into rte_etdev API.
Left extra free space in the queue info structures,
so extra fields could be added later without ABI breakage.
v2 changes:
- Add formal check for the qinfo input parameter.
- As suggested rename 'rx_qinfo/tx_qinfo' to 'rxq_info/txq_info'
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
lib/librte_ether/rte_ethdev.c | 54 ++++++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 77 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 130 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e13fde5..7dfe72a 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3629,6 +3629,60 @@ rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id,
}
int
+rte_eth_rx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_rxq_info *qinfo)
+{
+ struct rte_eth_dev *dev;
+
+ if (qinfo == NULL)
+ return -EINVAL;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ if (queue_id >= dev->data->nb_rx_queues) {
+ PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id);
+ return -EINVAL;
+ }
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rxq_info_get, -ENOTSUP);
+
+ memset(qinfo, 0, sizeof(*qinfo));
+ dev->dev_ops->rxq_info_get(dev, queue_id, qinfo);
+ return 0;
+}
+
+int
+rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_txq_info *qinfo)
+{
+ struct rte_eth_dev *dev;
+
+ if (qinfo == NULL)
+ return -EINVAL;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ if (queue_id >= dev->data->nb_tx_queues) {
+ PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id);
+ return -EINVAL;
+ }
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->txq_info_get, -ENOTSUP);
+
+ memset(qinfo, 0, sizeof(*qinfo));
+ dev->dev_ops->txq_info_get(dev, queue_id, qinfo);
+ return 0;
+}
+
+int
rte_eth_dev_set_mc_addr_list(uint8_t port_id,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 04c192d..5dd4c01 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -942,6 +942,30 @@ struct rte_eth_xstats {
uint64_t value;
};
+/**
+ * Ethernet device RX queue information strcuture.
+ * Used to retieve information about configured queue.
+ */
+struct rte_eth_rxq_info {
+ struct rte_mempool *mp; /**< mempool used by that queue. */
+ struct rte_eth_rxconf conf; /**< queue config parameters. */
+ uint8_t scattered_rx; /**< scattered packets RX supported. */
+ uint16_t nb_desc; /**< configured number of RXDs. */
+ uint16_t max_desc; /**< max allowed number of RXDs. */
+ uint16_t min_desc; /**< min allowed number of RXDs. */
+} __rte_cache_aligned;
+
+/**
+ * Ethernet device TX queue information strcuture.
+ * Used to retieve information about configured queue.
+ */
+struct rte_eth_txq_info {
+ struct rte_eth_txconf conf; /**< queue config parameters. */
+ uint16_t nb_desc; /**< configured number of TXDs. */
+ uint16_t max_desc; /**< max allowed number of TXDs. */
+ uint16_t min_desc; /**< min allowed number of TXDs. */
+} __rte_cache_aligned;
+
struct rte_eth_dev;
struct rte_eth_dev_callback;
@@ -1045,6 +1069,12 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
/**< @Check DD bit of specific RX descriptor */
+typedef void (*eth_rxq_info_get_t)(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, struct rte_eth_rxq_info *qinfo);
+
+typedef void (*eth_txq_info_get_t)(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, struct rte_eth_txq_info *qinfo);
+
typedef int (*mtu_set_t)(struct rte_eth_dev *dev, uint16_t mtu);
/**< @internal Set MTU. */
@@ -1389,8 +1419,13 @@ struct eth_dev_ops {
rss_hash_update_t rss_hash_update;
/** Get current RSS hash configuration. */
rss_hash_conf_get_t rss_hash_conf_get;
- eth_filter_ctrl_t filter_ctrl; /**< common filter control*/
+ eth_filter_ctrl_t filter_ctrl;
+ /**< common filter control. */
eth_set_mc_addr_list_t set_mc_addr_list; /**< set list of mcast addrs */
+ eth_rxq_info_get_t rxq_info_get;
+ /**< retrieve RX queue information. */
+ eth_txq_info_get_t txq_info_get;
+ /**< retrieve TX queue information. */
};
/**
@@ -3616,6 +3651,46 @@ int rte_eth_remove_rx_callback(uint8_t port_id, uint16_t queue_id,
int rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id,
struct rte_eth_rxtx_callback *user_cb);
+/**
+ * Retrieve information about given port's RX queue.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The RX queue on the Ethernet device for which information
+ * will be retrieved.
+ * @param qinfo
+ * A pointer to a structure of type *rte_eth_rxq_info_info* to be filled with
+ * the information of the Ethernet device.
+ *
+ * @return
+ * - 0: Success
+ * - -ENOTSUP: routine is not supported by the device PMD.
+ * - -EINVAL: The port_id or the queue_id is out of range.
+ */
+int rte_eth_rx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_rxq_info *qinfo);
+
+/**
+ * Retrieve information about given port's TX queue.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The TX queue on the Ethernet device for which information
+ * will be retrieved.
+ * @param qinfo
+ * A pointer to a structure of type *rte_eth_txq_info_info* to be filled with
+ * the information of the Ethernet device.
+ *
+ * @return
+ * - 0: Success
+ * - -ENOTSUP: routine is not supported by the device PMD.
+ * - -EINVAL: The port_id or the queue_id is out of range.
+ */
+int rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_txq_info *qinfo);
+
#ifdef __cplusplus
}
#endif
--
1.8.5.3
^ permalink raw reply [relevance 2%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 9:54 8% ` Morten Brørup
@ 2015-06-18 13:00 4% ` Dumitrescu, Cristian
0 siblings, 0 replies; 200+ results
From: Dumitrescu, Cristian @ 2015-06-18 13:00 UTC (permalink / raw)
To: Morten Brørup, Thomas Monjalon; +Cc: dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Morten Brørup
> Sent: Wednesday, June 17, 2015 10:54 AM
> To: Thomas Monjalon
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-announce] important design choices -
> statistics - ABI
>
> Dear Thomas,
>
> I don't have time to follow the DPDK Developers mailing list, but since you call
> for feedback, I would like to share my thoughts regarding these design
> choices.
>
>
> Regarding the statistics discussion:
>
> 1. The suggested solution assumes that, when statistics is disabled, the cost
> of allocating and maintaining zero-value statistics is negligible. If statistics
> counters are only available through accessor functions, this is probably true.
>
> However, if statistics counters are directly accessible, e.g. as elements in the
> fast path data structures of a library, maintaining zero-value statistics may a
> have memory and/or performance impact.
>
Counters are only accessible through API functions.
> Since the compile time flag
> CONFIG_RTE_<LIBRARY_NAME>_STATS_COLLECT already tells the
> application if the statistics are present or not, the application should simply
> use this flag to determine if statistics are accessible or not.
>
> 2. The suggested solution with only one single flag per library prevents
> implementing statistics with varying granularity for different purposes. E.g. a
> library could have one set of statistics counters for ordinary SNMP purposes,
> and another set of statistics counters for debugging/optimization purposes.
>
> Multiple flags per library should be possible. A hierarchy of flags per library is
> probably not required.
>
Morten, thank you for your input. It would be good if you could add your contribution to the of the guidelines documentation patch by replying to the thread that Thomas indicated: http://dpdk.org/ml/archives/dev/2015-June/019461.html.
Our initial stats patch submission had a much finer granularity of stats configuration: per object type instead of per library, but a lot of people on this mailing list are against this, so we are now looking for one configuration flag per library.
>
> Regarding the PHY speed ABI:
>
> 1. The Ethernet PHY ABI for speed, duplex, etc. should be common
> throughout the entire DPDK. It might be confusing if some
> structures/functions use a bitmask to indicate PHY
> speed/duplex/personality/etc. and other structures/functions use a
> combination of an unsigned integer, duplex flag, personality enumeration
> etc. (By personality enumeration, I am referring to PHYs with multiple
> electrical interfaces. E.g. a dual personality PHY might have both an RJ45
> copper interface and an SFP module interface, whereof only one can be
> active at any time.)
>
> 2. The auto-negotiation standard allows the PHY to announce (to its link
> partner) any subset of its capabilities to its link partner. E.g. a standard
> 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s in both
> half and full duplex and 1 Gbit/s full duplex) can be configured to announce
> 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities to its link partner.
> (Of course, more useful combinations are normally announced, but the
> purpose of the example is to show that any combination is possible.)
>
> The ABI for auto-negotiation should include options to select the list of
> capabilities to announce to the link partner. The Linux PHY ABI only allows
> forcing a selected speed and duplex (thereby disabling auto-negotiation) or
> enabling auto-negotiation (thereby announcing all possible speeds and
> duplex combinations the PHY is capable of). Don't make the same mistake in
> DPDK.
>
> PS: While working for Vitesse Semiconductors (an Ethernet chip company) a
> long time ago, I actually wrote the API for their line of Ethernet PHYs. So I
> have hands on experience in this area.
>
>
> Regarding the discussion about backwards/forwards compatibility in the ABI:
>
> 1. Sometimes, ABI breakage is required. That is the cost the users pay for
> getting the benefits from upgrading to the latest and greatest version of any
> library. The current solution of requiring acknowledgement from several
> qualified developers is fine - these developers will consider the cost/benefit
> on behalf of all the DPDK users and make a qualified decision.
>
> 2. It is my general experience that documentation is not always updated to
> reflect the fine details of the source code, and this also applies to release
> notes. For open source software, the primary point of documentation is
> usually the source code itself.
>
> 2a. It should be clearly visible directly in the DPDK source code (including
> makefiles etc.) which ABI (i.e. functions, macros, type definitions etc.) is the
> current, the deprecated, and the future.
>
> 2b. When a developer migrates a project using DPDK from a previous version
> of the DPDK, it should be easy for the developer to identify all DPDK ABI
> modifications and variants, e.g. by using a common indicator in the DPDK
> source code, such as LIBAPIVER, that developer can simply search for.
>
> 3. Adding special feature flags, e.g. CONFIG_RTE_EAL_RX_INTR, to indicate a
> breakage of the ABI, should only be done if it is the intention to keep both
> the current and the new variants of the feature in the DPDK in the future.
> Otherwise, such a flag should be combined with the standard ABI version
> indication, so it is clear that this feature belongs to certain versions (i.e.
> deprecated, current or future).
>
>
> Med venlig hilsen / kind regards
>
> Morten Brørup
> CTO
>
>
>
> SmartShare Systems A/S
> Tonsbakken 16-18
> DK-2740 Skovlunde
> Denmark
>
> Office +45 70 20 00 93
> Direct +45 89 93 50 22
> Mobile +45 25 40 82 12
>
> mb@smartsharesystems.com
> www.smartsharesystems.com
> -----Original Message-----
> From: announce [mailto:announce-bounces@dpdk.org] On Behalf Of
> Thomas Monjalon
> Sent: 17. juni 2015 01:30
> To: announce@dpdk.org
> Subject: [dpdk-announce] important design choices - statistics - ABI
>
> Hi all,
>
> Sometimes there are some important discussions about architecture or
> design which require opinions from several developers. Unfortunately, we
> cannot read every threads. Maybe that using the announce mailing list will
> help to bring more audience to these discussions.
> Please note that
> - the announce@ ML is moderated to keep a low traffic,
> - every announce email is forwarded to dev@ ML.
> In case you want to reply to this email, please use dev@dpdk.org address.
>
> There were some debates about software statistics disabling.
> Should they be always on or possibly disabled when compiled?
> We need to take a decision shortly and discuss (or agree) this proposal:
> http://dpdk.org/ml/archives/dev/2015-June/019461.html
>
> During the development of the release 2.0, there was an agreement to keep
> ABI compatibility or to bring new ABI while keeping old one during one
> release.
> In case it's not possible to have this transition, the (exceptional) break should
> be acknowledged by several developers.
> http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
> There were some interesting discussions but not a lot of participants:
> http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367
> /focus=8461
>
> During the current development cycle for the release 2.1, the ABI question
> arises many times in different threads.
> To add the hash key size field, it is proposed to use a struct padding gap:
> http://dpdk.org/ml/archives/dev/2015-June/019386.html
> To support the flow director for VF, there is no proposal yet:
> http://dpdk.org/ml/archives/dev/2015-June/019343.html
> To add the speed capability, it is proposed to break ABI in the release 2.2:
> http://dpdk.org/ml/archives/dev/2015-June/019225.html
> To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
> http://dpdk.org/ml/archives/dev/2015-June/019443.html
> To add the interrupt mode, it is proposed to add a build-time option
> CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking
> binary:
> http://dpdk.org/ml/archives/dev/2015-June/018947.html
> To add the packet type, there is a proposal to add a build-time option
> CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
> http://dpdk.org/ml/archives/dev/2015-June/019172.html
> We must also better document how to remove a deprecated ABI:
> http://dpdk.org/ml/archives/dev/2015-June/019465.html
> The ABI compatibility is a new constraint and we need to better understand
> what it means and how to proceed. Even the macros are not yet well
> documented:
> http://dpdk.org/ml/archives/dev/2015-June/019357.html
>
> Thanks for your attention and your participation in these important choices.
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v7 0/4] User-space Ethtool
2015-06-18 2:04 3% ` Stephen Hemminger
@ 2015-06-18 12:47 0% ` Wang, Liang-min
2015-06-23 15:19 0% ` Wang, Liang-min
0 siblings, 1 reply; 200+ results
From: Wang, Liang-min @ 2015-06-18 12:47 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: dev
>I agree with having a more complete API, but have some nits to pick.
>Could the API be more abstract to reduce ABI issues in future?
Which API? Are you referring to the APIs over ethdev level, or something else?
More abstract on input/output data structure definition or else? Could you be more specific?
>I know choosing names is hard, but as a Linux developer ethtool has a very specific meaning to me.
>This API encompasses things broader than Linux ethtool and has different semantics therefore
>not sure having something in DPDK with same name is really a good idea.
>
>It would be better to call it something else like netdev_?? Or dpnet_??
Just to clarify the naming suggestion, in this patch, the prefix “ethtool” only appears on example and on this patch description.
Are you suggesting changing the name over example/l2fwd-ethtool or on this patch description, or may be both?
^ permalink raw reply [relevance 0%]
* Re: [dpdk-dev] [PATCH 2/6] hash: replace existing hash library with cuckoo hash implementation
@ 2015-06-18 9:50 4% ` Bruce Richardson
0 siblings, 0 replies; 200+ results
From: Bruce Richardson @ 2015-06-18 9:50 UTC (permalink / raw)
To: Pablo de Lara; +Cc: dev
On Fri, Jun 05, 2015 at 03:33:20PM +0100, Pablo de Lara wrote:
> This patch replaces the existing hash library with another approach,
> using the Cuckoo Hash method to resolve collisions (open addressing),
> which pushes items from a full bucket when a new entry tries
> to be added in it, storing the evicted entry in an alternative location,
> using a secondary hash function.
>
> This gives the user the ability to store more entries when a bucket
> is full, in comparison with the previous implementation.
> Therefore, the unit test has been updated, as some scenarios have changed
> (such as the previous removed restriction).
>
> Also note that the API has not been changed, although new fields
> have been added in the rte_hash structure.
> The main change when creating a new table is that the number of entries
> per bucket is fixed now, so its parameter is ignored now
> (still there to maintain the same parameters structure).
>
> As a last note, the maximum burst size in lookup_burst function
> hash been increased to 64, to improve performance.
>
> Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Hi Pablo,
Some review comments below.
/Bruce
> ---
> app/test/test_hash.c | 86 +----
> lib/librte_hash/rte_hash.c | 797 ++++++++++++++++++++++++++++++++++-----------
> lib/librte_hash/rte_hash.h | 157 +++++----
> 3 files changed, 721 insertions(+), 319 deletions(-)
>
> diff --git a/app/test/test_hash.c b/app/test/test_hash.c
> index 1da27c5..4ef99ee 100644
> --- a/app/test/test_hash.c
> +++ b/app/test/test_hash.c
> @@ -169,7 +169,6 @@ static struct flow_key keys[5] = { {
> /* Parameters used for hash table in unit test functions. Name set later. */
> static struct rte_hash_parameters ut_params = {
> .entries = 64,
> - .bucket_entries = 4,
> .key_len = sizeof(struct flow_key), /* 13 */
> .hash_func = rte_jhash,
> .hash_func_init_val = 0,
> @@ -527,21 +526,18 @@ static int test_five_keys(void)
> /*
> * Add keys to the same bucket until bucket full.
> * - add 5 keys to the same bucket (hash created with 4 keys per bucket):
> - * first 4 successful, 5th unsuccessful
> - * - lookup the 5 keys: 4 hits, 1 miss
> - * - add the 5 keys again: 4 OK, one error as bucket is full
> - * - lookup the 5 keys: 4 hits (updated data), 1 miss
> - * - delete the 5 keys: 5 OK (even if the 5th is not in the table)
> + * first 4 successful, 5th successful, pushing existing item in bucket
> + * - lookup the 5 keys: 5 hits
> + * - add the 5 keys again: 5 OK
> + * - lookup the 5 keys: 5 hits (updated data)
> + * - delete the 5 keys: 5 OK
> * - lookup the 5 keys: 5 misses
> - * - add the 5th key: OK
> - * - lookup the 5th key: hit
> */
> static int test_full_bucket(void)
> {
> struct rte_hash_parameters params_pseudo_hash = {
> .name = "test4",
> .entries = 64,
> - .bucket_entries = 4,
> .key_len = sizeof(struct flow_key), /* 13 */
> .hash_func = pseudo_hash,
> .hash_func_init_val = 0,
> @@ -555,7 +551,7 @@ static int test_full_bucket(void)
> handle = rte_hash_create(¶ms_pseudo_hash);
> RETURN_IF_ERROR(handle == NULL, "hash creation failed");
>
> - /* Fill bucket*/
> + /* Fill bucket */
> for (i = 0; i < 4; i++) {
> pos[i] = rte_hash_add_key(handle, &keys[i]);
> print_key_info("Add", &keys[i], pos[i]);
> @@ -563,47 +559,36 @@ static int test_full_bucket(void)
> "failed to add key (pos[%u]=%d)", i, pos[i]);
> expected_pos[i] = pos[i];
> }
> - /* This shouldn't work because the bucket is full */
> + /* This should work and will push one of the items in the bucket because it is full */
> pos[4] = rte_hash_add_key(handle, &keys[4]);
> print_key_info("Add", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] != -ENOSPC,
> - "fail: added key to full bucket (pos[4]=%d)", pos[4]);
> + RETURN_IF_ERROR(pos[4] < 0,
> + "failed to add key (pos[4]=%d)", pos[4]);
> + expected_pos[5] = pos[5];
>
> /* Lookup */
> - for (i = 0; i < 4; i++) {
> + for (i = 0; i < 5; i++) {
> pos[i] = rte_hash_lookup(handle, &keys[i]);
> print_key_info("Lkp", &keys[i], pos[i]);
> RETURN_IF_ERROR(pos[i] != expected_pos[i],
> "failed to find key (pos[%u]=%d)", i, pos[i]);
> }
> - pos[4] = rte_hash_lookup(handle, &keys[4]);
> - print_key_info("Lkp", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] != -ENOENT,
> - "fail: found non-existent key (pos[4]=%d)", pos[4]);
>
> /* Add - update */
> - for (i = 0; i < 4; i++) {
> + for (i = 0; i < 5; i++) {
> pos[i] = rte_hash_add_key(handle, &keys[i]);
> print_key_info("Add", &keys[i], pos[i]);
> RETURN_IF_ERROR(pos[i] != expected_pos[i],
> "failed to add key (pos[%u]=%d)", i, pos[i]);
> }
> - pos[4] = rte_hash_add_key(handle, &keys[4]);
> - print_key_info("Add", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] != -ENOSPC,
> - "fail: added key to full bucket (pos[4]=%d)", pos[4]);
>
> /* Lookup */
> - for (i = 0; i < 4; i++) {
> + for (i = 0; i < 5; i++) {
> pos[i] = rte_hash_lookup(handle, &keys[i]);
> print_key_info("Lkp", &keys[i], pos[i]);
> RETURN_IF_ERROR(pos[i] != expected_pos[i],
> "failed to find key (pos[%u]=%d)", i, pos[i]);
> }
> - pos[4] = rte_hash_lookup(handle, &keys[4]);
> - print_key_info("Lkp", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] != -ENOENT,
> - "fail: found non-existent key (pos[4]=%d)", pos[4]);
>
> /* Delete 1 key, check other keys are still found */
> pos[1] = rte_hash_del_key(handle, &keys[1]);
> @@ -623,35 +608,21 @@ static int test_full_bucket(void)
> RETURN_IF_ERROR(pos[1] < 0, "failed to add key (pos[1]=%d)", pos[1]);
>
> /* Delete */
> - for (i = 0; i < 4; i++) {
> + for (i = 0; i < 5; i++) {
> pos[i] = rte_hash_del_key(handle, &keys[i]);
> print_key_info("Del", &keys[i], pos[i]);
> RETURN_IF_ERROR(pos[i] != expected_pos[i],
> "failed to delete key (pos[%u]=%d)", i, pos[i]);
> }
> - pos[4] = rte_hash_del_key(handle, &keys[4]);
> - print_key_info("Del", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] != -ENOENT,
> - "fail: deleted non-existent key (pos[4]=%d)", pos[4]);
>
> /* Lookup */
> - for (i = 0; i < 4; i++) {
> + for (i = 0; i < 5; i++) {
> pos[i] = rte_hash_lookup(handle, &keys[i]);
> print_key_info("Lkp", &keys[i], pos[i]);
> RETURN_IF_ERROR(pos[i] != -ENOENT,
> "fail: found non-existent key (pos[%u]=%d)", i, pos[i]);
> }
>
> - /* Add and lookup the 5th key */
> - pos[4] = rte_hash_add_key(handle, &keys[4]);
> - print_key_info("Add", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] < 0, "failed to add key (pos[4]=%d)", pos[4]);
> - expected_pos[4] = pos[4];
> - pos[4] = rte_hash_lookup(handle, &keys[4]);
> - print_key_info("Lkp", &keys[4], pos[4]);
> - RETURN_IF_ERROR(pos[4] != expected_pos[4],
> - "failed to find key (pos[4]=%d)", pos[4]);
> -
> rte_hash_free(handle);
>
> /* Cover the NULL case. */
> @@ -1017,18 +988,8 @@ static int test_hash_creation_with_bad_parameters(void)
> }
>
> memcpy(¶ms, &ut_params, sizeof(params));
> - params.name = "creation_with_bad_parameters_1";
> - params.bucket_entries = RTE_HASH_BUCKET_ENTRIES_MAX + 1;
> - handle = rte_hash_create(¶ms);
> - if (handle != NULL) {
> - rte_hash_free(handle);
> - printf("Impossible creating hash sucessfully with bucket_entries in parameter exceeded\n");
> - return -1;
> - }
> -
> - memcpy(¶ms, &ut_params, sizeof(params));
> params.name = "creation_with_bad_parameters_2";
> - params.entries = params.bucket_entries - 1;
> + params.entries = RTE_HASH_BUCKET_ENTRIES - 1;
> handle = rte_hash_create(¶ms);
> if (handle != NULL) {
> rte_hash_free(handle);
> @@ -1048,16 +1009,6 @@ static int test_hash_creation_with_bad_parameters(void)
>
> memcpy(¶ms, &ut_params, sizeof(params));
> params.name = "creation_with_bad_parameters_4";
> - params.bucket_entries = params.bucket_entries - 1;
> - handle = rte_hash_create(¶ms);
> - if (handle != NULL) {
> - rte_hash_free(handle);
> - printf("Impossible creating hash sucessfully if bucket_entries in parameter is not power of 2\n");
> - return -1;
> - }
> -
> - memcpy(¶ms, &ut_params, sizeof(params));
> - params.name = "creation_with_bad_parameters_5";
> params.key_len = 0;
> handle = rte_hash_create(¶ms);
> if (handle != NULL) {
> @@ -1067,7 +1018,7 @@ static int test_hash_creation_with_bad_parameters(void)
> }
>
> memcpy(¶ms, &ut_params, sizeof(params));
> - params.name = "creation_with_bad_parameters_6";
> + params.name = "creation_with_bad_parameters_5";
> params.key_len = RTE_HASH_KEY_LENGTH_MAX + 1;
> handle = rte_hash_create(¶ms);
> if (handle != NULL) {
> @@ -1077,7 +1028,7 @@ static int test_hash_creation_with_bad_parameters(void)
> }
>
> memcpy(¶ms, &ut_params, sizeof(params));
> - params.name = "creation_with_bad_parameters_7";
> + params.name = "creation_with_bad_parameters_6";
> params.socket_id = RTE_MAX_NUMA_NODES + 1;
> handle = rte_hash_create(¶ms);
> if (handle != NULL) {
> @@ -1158,7 +1109,6 @@ static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03,
> static struct rte_hash_parameters hash_params_ex = {
> .name = NULL,
> .entries = 64,
> - .bucket_entries = 4,
> .key_len = 0,
> .hash_func = NULL,
> .hash_func_init_val = 0,
> diff --git a/lib/librte_hash/rte_hash.c b/lib/librte_hash/rte_hash.c
> index 9245716..cbfe17e 100644
> --- a/lib/librte_hash/rte_hash.c
> +++ b/lib/librte_hash/rte_hash.c
> @@ -1,7 +1,7 @@
> /*-
> * BSD LICENSE
> *
> - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
> * All rights reserved.
> *
> * Redistribution and use in source and binary forms, with or without
> @@ -83,64 +83,12 @@ EAL_REGISTER_TAILQ(rte_hash_tailq)
> #define DEFAULT_HASH_FUNC rte_jhash
> #endif
>
> -/* Signature bucket size is a multiple of this value */
> -#define SIG_BUCKET_ALIGNMENT 16
> -
> -/* Stoered key size is a multiple of this value */
> -#define KEY_ALIGNMENT 16
> +/* Bucket size is a multiple of this value */
> +#define BUCKET_ALIGNMENT 16
Why this value? Why not just CACHE_LINE_SIZE? In fact, given that the buckets
in this implementation are now a fixed size, this is unnecessary. The buckets are
always one cache line in size, due to __rte_cache_aligned on the definition.
>
> /* The high bit is always set in real signatures */
> #define NULL_SIGNATURE 0
>
> -/* Returns a pointer to the first signature in specified bucket. */
> -static inline hash_sig_t *
> -get_sig_tbl_bucket(const struct rte_hash *h, uint32_t bucket_index)
> -{
> - return (hash_sig_t *)
> - &(h->sig_tbl[bucket_index * h->sig_tbl_bucket_size]);
> -}
> -
> -/* Returns a pointer to the first key in specified bucket. */
> -static inline uint8_t *
> -get_key_tbl_bucket(const struct rte_hash *h, uint32_t bucket_index)
> -{
> - return (uint8_t *) &(h->key_tbl[bucket_index * h->bucket_entries *
> - h->key_tbl_key_size]);
> -}
> -
> -/* Returns a pointer to a key at a specific position in a specified bucket. */
> -static inline void *
> -get_key_from_bucket(const struct rte_hash *h, uint8_t *bkt, uint32_t pos)
> -{
> - return (void *) &bkt[pos * h->key_tbl_key_size];
> -}
> -
> -/* Does integer division with rounding-up of result. */
> -static inline uint32_t
> -div_roundup(uint32_t numerator, uint32_t denominator)
> -{
> - return (numerator + denominator - 1) / denominator;
> -}
> -
> -/* Increases a size (if needed) to a multiple of alignment. */
> -static inline uint32_t
> -align_size(uint32_t val, uint32_t alignment)
> -{
> - return alignment * div_roundup(val, alignment);
> -}
> -
> -/* Returns the index into the bucket of the first occurrence of a signature. */
> -static inline int
> -find_first(uint32_t sig, const uint32_t *sig_bucket, uint32_t num_sigs)
> -{
> - uint32_t i;
> - for (i = 0; i < num_sigs; i++) {
> - if (sig == sig_bucket[i])
> - return i;
> - }
> - return -1;
> -}
> -
> struct rte_hash *
> rte_hash_find_existing(const char *name)
> {
> @@ -165,25 +113,49 @@ rte_hash_find_existing(const char *name)
> return h;
> }
>
> +/* Does integer division with rounding-up of result. */
> +static inline uint32_t
> +div_roundup(uint32_t numerator, uint32_t denominator)
> +{
> + return (numerator + denominator - 1) / denominator;
> +}
> +
> +/* Increases a size (if needed) to a multiple of alignment. */
> +static inline uint32_t
> +align_size(uint32_t val, uint32_t alignment)
> +{
> + return alignment * div_roundup(val, alignment);
> +}
There are already inline functions/macros for alignment in rte_common.h, that
should be used if possible.
> +
> struct rte_hash *
> rte_hash_create(const struct rte_hash_parameters *params)
> {
> struct rte_hash *h = NULL;
> struct rte_tailq_entry *te;
> - uint32_t num_buckets, sig_bucket_size, key_size,
> - hash_tbl_size, sig_tbl_size, key_tbl_size, mem_size;
> + uint32_t num_buckets, bucket_size,
> + tbl_size, mem_size, hash_struct_size;
> char hash_name[RTE_HASH_NAMESIZE];
> struct rte_hash_list *hash_list;
> + void *k = NULL;
> + struct rte_ring *r = NULL;
> + char ring_name[RTE_RING_NAMESIZE];
> + unsigned key_entry_size;
> + const unsigned anyalignment = 0;
> + unsigned i;
> + void *ptr;
>
> hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list);
>
> + if (params == NULL) {
> + RTE_LOG(ERR, HASH, "rte_hash_create has no parameters\n");
> + return NULL;
> + }
> +
> /* Check for valid parameters */
> - if ((params == NULL) ||
> - (params->entries > RTE_HASH_ENTRIES_MAX) ||
> - (params->bucket_entries > RTE_HASH_BUCKET_ENTRIES_MAX) ||
> - (params->entries < params->bucket_entries) ||
> + if ((params->entries > RTE_HASH_ENTRIES_MAX) ||
> + (params->entries < RTE_HASH_BUCKET_ENTRIES) ||
> !rte_is_power_of_2(params->entries) ||
> - !rte_is_power_of_2(params->bucket_entries) ||
> + !rte_is_power_of_2(RTE_HASH_BUCKET_ENTRIES) ||
> (params->key_len == 0) ||
> (params->key_len > RTE_HASH_KEY_LENGTH_MAX)) {
> rte_errno = EINVAL;
> @@ -194,19 +166,18 @@ rte_hash_create(const struct rte_hash_parameters *params)
> snprintf(hash_name, sizeof(hash_name), "HT_%s", params->name);
>
> /* Calculate hash dimensions */
> - num_buckets = params->entries / params->bucket_entries;
> - sig_bucket_size = align_size(params->bucket_entries *
> - sizeof(hash_sig_t), SIG_BUCKET_ALIGNMENT);
> - key_size = align_size(params->key_len, KEY_ALIGNMENT);
> + num_buckets = params->entries / RTE_HASH_BUCKET_ENTRIES;
> +
> + bucket_size = align_size(sizeof(struct rte_hash_bucket), BUCKET_ALIGNMENT);
unnecessary, due to cache line ailgnment of the struct.
>
> - hash_tbl_size = align_size(sizeof(struct rte_hash), RTE_CACHE_LINE_SIZE);
> - sig_tbl_size = align_size(num_buckets * sig_bucket_size,
> + hash_struct_size = align_size(sizeof(struct rte_hash), RTE_CACHE_LINE_SIZE);
I don't think this is necessary. Better to make structure cache line aligned, and
then just use sizeof without any additional calculations on it's size.
> + tbl_size = align_size(num_buckets * bucket_size,
> RTE_CACHE_LINE_SIZE);
Again, unecessary alignment calculation.
> - key_tbl_size = align_size(num_buckets * key_size *
> - params->bucket_entries, RTE_CACHE_LINE_SIZE);
>
> /* Total memory required for hash context */
> - mem_size = hash_tbl_size + sig_tbl_size + key_tbl_size;
> + mem_size = hash_struct_size + tbl_size;
> +
> + key_entry_size = params->key_len;
Is this not a case where we do want some sort of alignment on our keys, just to
reduce the chances of a key crossing a cache line boundary?
>
> rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
>
> @@ -216,6 +187,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
> if (strncmp(params->name, h->name, RTE_HASH_NAMESIZE) == 0)
> break;
> }
> + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
> if (te != NULL)
> goto exit;
>
> @@ -226,36 +198,73 @@ rte_hash_create(const struct rte_hash_parameters *params)
> }
>
> h = (struct rte_hash *)rte_zmalloc_socket(hash_name, mem_size,
> - RTE_CACHE_LINE_SIZE, params->socket_id);
> + RTE_CACHE_LINE_SIZE, params->socket_id);
> +
> if (h == NULL) {
> RTE_LOG(ERR, HASH, "memory allocation failed\n");
> rte_free(te);
> goto exit;
> }
>
> + k = rte_zmalloc_socket(NULL, key_entry_size * (params->entries + 1),
> + anyalignment, params->socket_id);
> +
> + if (k == NULL) {
> + RTE_LOG(ERR, HASH, "memory allocation failed\n");
> + h = NULL;
> + rte_free(te);
> + rte_free(h);
Rather than building-up an ever increasing list of memory to be freed on each
exit branch, define a separate error label and always free all the memory pointers
allocated during the run. The rte_free() API has no effect on NULL pointers, so
it can be safe to do so (assuming you NULL-initialize all vars first).
> + goto exit;
> + }
> +
> + snprintf(ring_name, sizeof(ring_name), "HT_%s", params->name);
> + r = rte_ring_lookup(ring_name);
> + if (r != NULL) {
> + /* clear the free ring */
> + while (rte_ring_dequeue(r, &ptr) == 0)
> + rte_pause();
> + } else
> + r = rte_ring_create(ring_name, rte_align32pow2(params->entries),
> + params->socket_id, 0);
> + if (r == NULL) {
> + RTE_LOG(ERR, HASH, "memory allocation failed\n");
> + rte_free(te);
> + rte_free(h);
> + h = NULL;
> + rte_free(k);
> + goto exit;
> + }
> +
> /* Setup hash context */
> snprintf(h->name, sizeof(h->name), "%s", params->name);
> h->entries = params->entries;
> - h->bucket_entries = params->bucket_entries;
> + h->bucket_entries = RTE_HASH_BUCKET_ENTRIES;
> h->key_len = params->key_len;
> + h->key_entry_size = key_entry_size;
> h->hash_func_init_val = params->hash_func_init_val;
> + h->socket_id = params->socket_id;
> +
> h->num_buckets = num_buckets;
> h->bucket_bitmask = h->num_buckets - 1;
> - h->sig_msb = 1 << (sizeof(hash_sig_t) * 8 - 1);
> - h->sig_tbl = (uint8_t *)h + hash_tbl_size;
> - h->sig_tbl_bucket_size = sig_bucket_size;
> - h->key_tbl = h->sig_tbl + sig_tbl_size;
> - h->key_tbl_key_size = key_size;
> + h->buckets = (struct rte_hash_bucket *)((uint8_t *)h + hash_struct_size);
You can avoid the addition and typecasting by adding
struct rte_hash_bucket buckets[0] __rte_cache_aligned;
as the last field in your rte_hash structure.
> h->hash_func = (params->hash_func == NULL) ?
> DEFAULT_HASH_FUNC : params->hash_func;
>
> + h->sig_msb = 1ULL << (sizeof(uint64_t) * 8 - 1);
8 == CHAR_BIT
> + h->sig_secondary = 1ULL << (sizeof(uint64_t) * 8 - 2);
> +
h->sig_secondary = h->sig_msb >> 1; // ??
> + h->key_store = k;
> + h->free_slots = r;
> te->data = (void *) h;
>
> - TAILQ_INSERT_TAIL(hash_list, te, next);
> + /* populate the free slots ring. Entry zero is reserved for key misses */
> + for (i = 1; i < params->entries + 1; i++)
> + rte_ring_sp_enqueue(r, (void *)((uintptr_t) i));
>
> -exit:
> + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
> + TAILQ_INSERT_TAIL(hash_list, te, next);
> rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
> -
> +exit:
> return h;
> }
>
> @@ -287,49 +296,164 @@ rte_hash_free(struct rte_hash *h)
>
> rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
>
> + rte_free(h->key_store);
> rte_free(h);
> rte_free(te);
> }
>
> static inline int32_t
> -__rte_hash_add_key_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig)
> +run_cuckoo(const struct rte_hash *h, struct rte_hash_bucket *bkt, uint32_t key_idx,
> + uint64_t hash, uint64_t original_hash, const void *original_key)
> {
> - hash_sig_t *sig_bucket;
> - uint8_t *key_bucket;
> - uint32_t bucket_index, i;
> - int32_t pos;
> -
> - /* Get the hash signature and bucket index */
> - sig |= h->sig_msb;
> - bucket_index = sig & h->bucket_bitmask;
> - sig_bucket = get_sig_tbl_bucket(h, bucket_index);
> - key_bucket = get_key_tbl_bucket(h, bucket_index);
> -
> - /* Check if key is already present in the hash */
> - for (i = 0; i < h->bucket_entries; i++) {
> - if ((sig == sig_bucket[i]) &&
> - likely(memcmp(key, get_key_from_bucket(h, key_bucket, i),
> - h->key_len) == 0)) {
> - return bucket_index * h->bucket_entries + i;
> + /* idx = 0 if primary, 1 if secondary */
> + unsigned idx;
> + static unsigned number_pushes;
> + void *k, *keys = h->key_store;
> + unsigned i, j;
> +
> + uint64_t hash_stored;
> + uint32_t key_idx_stored;
> + uint32_t bucket_stored_idx;
> + struct rte_hash_bucket *bkt_stored;
> +
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + /* Check if slot is available */
> + if (likely(bkt->signatures[i] == NULL_SIGNATURE)) {
> + bkt->signatures[i] = hash;
> + bkt->key_idx[i] = key_idx;
> + number_pushes = 0;
> + return bkt->key_idx[i];
> + }
> + }
> +
> + /*
> + * If number of pushes has exceeded a certain limit, it
> + * is very likely that it has entered in a loop, need rehasing
> + */
> + if (++number_pushes > 1 && hash == original_hash) {
> + k = (char *)keys + key_idx * h->key_entry_size;
> + if (!memcmp(k, original_key, h->key_len)) {
> + rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)key_idx));
> + number_pushes = 0;
> + /*
> + * Indicates to the user that key could not be added,
> + * so he can rehash and add it again or decide not to.
> + */
> + return -EAGAIN;
> }
> }
>
> - /* Check if any free slot within the bucket to add the new key */
> - pos = find_first(NULL_SIGNATURE, sig_bucket, h->bucket_entries);
> + /*
> + * Push existing item (search for bucket with space in alternative locations)
> + * to its alternative location
> + */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + /*
> + * Check if item was stored in its primary/secondary location,
> + * to get the hash in the alternative location
> + */
> + idx = !(bkt->signatures[i] & (h->sig_secondary));
> + key_idx_stored = bkt->key_idx[i];
> + k = (char *)keys + key_idx_stored * h->key_entry_size;
> +
> + if (idx == 0)
> + hash_stored = rte_hash_hash(h, k);
> + else
> + hash_stored = rte_hash_secondary_hash(bkt->signatures[i]);
> +
> + bucket_stored_idx = hash_stored & h->bucket_bitmask;
> + bkt_stored = &h->buckets[bucket_stored_idx];
> + hash_stored |= h->sig_msb;
> +
> + if (idx != 0)
> + hash_stored |= h->sig_secondary;
> +
> + for (j = 0; j < RTE_HASH_BUCKET_ENTRIES; j++) {
> + if (bkt_stored->signatures[j] == NULL_SIGNATURE)
> + break;
> + }
> +
> + if (j != RTE_HASH_BUCKET_ENTRIES)
> + break;
> + }
> +
> + /* Push existing item (if all alternative buckets are full, pick the last one) */
> + if (i == RTE_HASH_BUCKET_ENTRIES)
> + i -= 1;
> +
> + bkt->signatures[i] = hash;
> + bkt->key_idx[i] = key_idx;
> +
> + /* There is an empty slot in the alternative bucket */
> + if (j != RTE_HASH_BUCKET_ENTRIES) {
> + bkt_stored->signatures[j] = hash_stored;
> + bkt_stored->key_idx[j] = key_idx_stored;
> +
> + number_pushes = 0;
> + return bkt_stored->key_idx[j];
> + } else
> + return run_cuckoo(h, bkt_stored, key_idx_stored, hash_stored,
> + original_hash, original_key);
> +}
> +
> +static inline int32_t
> +__rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key,
> + hash_sig_t sig)
> +{
> + uint64_t hash0, bucket_idx0, hash1, bucket_idx1;
> + unsigned i;
> + struct rte_hash_bucket *bkt0, *bkt1;
> + void *k, *keys = h->key_store;
> + void *slot_id;
> +
> + hash0 = sig;
> + bucket_idx0 = hash0 & h->bucket_bitmask;
> + hash0 |= h->sig_msb;
> +
> + bkt0 = &h->buckets[bucket_idx0];
>
> - if (unlikely(pos < 0))
> + hash1 = rte_hash_secondary_hash(hash0);
Should this not be done before you go setting the msb on hash0?
> +
> + bucket_idx1 = hash1 & h->bucket_bitmask;
> + hash1 |= h->sig_msb;
> + /* Secondary location, add an extra 1 in the second MSB */
> + hash1 |= h->sig_secondary;
> +
> + bkt1 = &h->buckets[bucket_idx1];
> +
> + /* Check if key is already inserted in primary location */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + if (bkt0->signatures[i] == hash0) {
> + k = (char *)keys + bkt0->key_idx[i] * h->key_entry_size;
> + if (memcmp(key, k, h->key_len) == 0)
> + return bkt0->key_idx[i];
> + }
> + }
> +
> + /* Check if key is already inserted in secondary location */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + if (bkt1->signatures[i] == hash1) {
> + k = (char *)keys + bkt1->key_idx[i] * h->key_entry_size;
> + if (memcmp(key, k, h->key_len) == 0)
> + return bkt1->key_idx[i];
> + }
> + }
> +
> + k = (char *)keys + bkt0->key_idx[i] * h->key_entry_size;
Useless statement. You assign to k again just 3 lines further down.
> + if (rte_ring_sc_dequeue(h->free_slots, &slot_id) != 0)
> return -ENOSPC;
>
> - /* Add the new key to the bucket */
> - sig_bucket[pos] = sig;
> - rte_memcpy(get_key_from_bucket(h, key_bucket, pos), key, h->key_len);
> - return bucket_index * h->bucket_entries + pos;
> + /* Copy key*/
> + k = (char *)keys + (uintptr_t)slot_id * h->key_entry_size;
> + memcpy(k, key, h->key_len);
> +
> + /* Run cuckoo algorithm */
> + return run_cuckoo(h, bkt0, (uint32_t)((uintptr_t) slot_id), hash0, hash0, key);
Is this not meant to be hash0, hash1 for parameters 4 & 5?
> }
>
> int32_t
> rte_hash_add_key_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig)
> + const void *key, hash_sig_t sig)
> {
> RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
> return __rte_hash_add_key_with_hash(h, key, sig);
> @@ -343,26 +467,45 @@ rte_hash_add_key(const struct rte_hash *h, const void *key)
> }
>
> static inline int32_t
> -__rte_hash_del_key_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig)
> +__rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key,
> + hash_sig_t sig)
> {
> - hash_sig_t *sig_bucket;
> - uint8_t *key_bucket;
> - uint32_t bucket_index, i;
> -
> - /* Get the hash signature and bucket index */
> - sig = sig | h->sig_msb;
> - bucket_index = sig & h->bucket_bitmask;
> - sig_bucket = get_sig_tbl_bucket(h, bucket_index);
> - key_bucket = get_key_tbl_bucket(h, bucket_index);
> -
> - /* Check if key is already present in the hash */
> - for (i = 0; i < h->bucket_entries; i++) {
> - if ((sig == sig_bucket[i]) &&
> - likely(memcmp(key, get_key_from_bucket(h, key_bucket, i),
> - h->key_len) == 0)) {
> - sig_bucket[i] = NULL_SIGNATURE;
> - return bucket_index * h->bucket_entries + i;
> + uint64_t hash, bucket_idx;
> + unsigned i;
> + struct rte_hash_bucket *bkt;
> + void *k, *keys = h->key_store;
> +
> + hash = sig;
> + bucket_idx = hash & h->bucket_bitmask;
> + hash |= h->sig_msb;
> +
> + bkt = &h->buckets[bucket_idx];
> +
> + /* Check if key is in primary location */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + if (bkt->signatures[i] == hash) {
> + k = (char *)keys + bkt->key_idx[i] * h->key_entry_size;
> + if (memcmp(key, k, h->key_len) == 0)
> + return bkt->key_idx[i];
> + }
> + }
> +
> + /* Calculate secondary hash */
> + hash = rte_hash_secondary_hash(hash);
> +
> + bucket_idx = hash & h->bucket_bitmask;
> + hash |= h->sig_msb;
> + /* Secondary location, add an extra 1 in the second MSB */
> + hash |= h->sig_secondary;
> +
> + bkt = &h->buckets[bucket_idx];
> +
> + /* Check if key is in secondary location */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + if (bkt->signatures[i] == hash) {
> + k = (char *)keys + bkt->key_idx[i] * h->key_entry_size;
> + if (memcmp(key, k, h->key_len) == 0)
> + return bkt->key_idx[i];
> }
> }
>
> @@ -370,40 +513,66 @@ __rte_hash_del_key_with_hash(const struct rte_hash *h,
> }
>
> int32_t
> -rte_hash_del_key_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig)
> +rte_hash_lookup_with_hash(const struct rte_hash *h,
> + const void *key, hash_sig_t sig)
> {
> RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
> - return __rte_hash_del_key_with_hash(h, key, sig);
> + return __rte_hash_lookup_with_hash(h, key, sig);
> }
>
> int32_t
> -rte_hash_del_key(const struct rte_hash *h, const void *key)
> +rte_hash_lookup(const struct rte_hash *h, const void *key)
> {
> RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
> - return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key));
> + return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key));
> }
>
> static inline int32_t
> -__rte_hash_lookup_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig)
> +__rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key,
> + hash_sig_t sig)
> {
> - hash_sig_t *sig_bucket;
> - uint8_t *key_bucket;
> - uint32_t bucket_index, i;
> -
> - /* Get the hash signature and bucket index */
> - sig |= h->sig_msb;
> - bucket_index = sig & h->bucket_bitmask;
> - sig_bucket = get_sig_tbl_bucket(h, bucket_index);
> - key_bucket = get_key_tbl_bucket(h, bucket_index);
> -
> - /* Check if key is already present in the hash */
> - for (i = 0; i < h->bucket_entries; i++) {
> - if ((sig == sig_bucket[i]) &&
> - likely(memcmp(key, get_key_from_bucket(h, key_bucket, i),
> - h->key_len) == 0)) {
> - return bucket_index * h->bucket_entries + i;
> + uint64_t hash, bucket_idx;
> + unsigned i;
> + struct rte_hash_bucket *bkt;
> + void *k, *keys = h->key_store;
> +
> + hash = sig;
> + bucket_idx = hash & h->bucket_bitmask;
> + hash |= h->sig_msb;
> +
> + bkt = &h->buckets[bucket_idx];
> +
> + /* Check if key is in primary location */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + if (bkt->signatures[i] == hash) {
> + k = (char *)keys + bkt->key_idx[i] * h->key_entry_size;
> + if (memcmp(key, k, h->key_len) == 0) {
> + bkt->signatures[i] = NULL_SIGNATURE;
> + rte_ring_sp_enqueue(h->free_slots,
> + (void *)((uintptr_t)bkt->key_idx[i]));
> + return bkt->key_idx[i];
> + }
> + }
> + }
> +
> + hash = rte_hash_secondary_hash(hash);
> + bucket_idx = hash & h->bucket_bitmask;
> + hash |= h->sig_msb;
> + /* Secondary location, add an extra 1 in the second MSB */
> + hash |= h->sig_secondary;
> +
> + bkt = &h->buckets[bucket_idx];
> +
> + /* Check if key is in secondary location */
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + if (bkt->signatures[i] == hash) {
> + k = (char *)keys + bkt->key_idx[i] * h->key_entry_size;
> + if (memcmp(key, k, h->key_len) == 0) {
> + bkt->signatures[i] = NULL_SIGNATURE;
> + rte_ring_sp_enqueue(h->free_slots,
> + (void *)((uintptr_t)bkt->key_idx[i]));
> + return bkt->key_idx[i];
> + }
> }
> }
>
> @@ -411,61 +580,313 @@ __rte_hash_lookup_with_hash(const struct rte_hash *h,
> }
>
> int32_t
> -rte_hash_lookup_with_hash(const struct rte_hash *h,
> +rte_hash_del_key_with_hash(const struct rte_hash *h,
> const void *key, hash_sig_t sig)
> {
> RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
> - return __rte_hash_lookup_with_hash(h, key, sig);
> + return __rte_hash_del_key_with_hash(h, key, sig);
> }
>
> int32_t
> -rte_hash_lookup(const struct rte_hash *h, const void *key)
> +rte_hash_del_key(const struct rte_hash *h, const void *key)
> {
> RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
> - return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key));
> + return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key));
> }
>
> -int
> -rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
> - uint32_t num_keys, int32_t *positions)
> +/* Lookup bulk stage 0: Calculate next primary/secondary hash value (from new key) */
> +static inline void
> +lookup_stage0(unsigned *idx, uint64_t *lookup_mask,
> + uint64_t *primary_hash, uint64_t *secondary_hash,
> + const void * const *keys, const struct rte_hash *h)
> {
> - uint32_t i, j, bucket_index;
> - hash_sig_t sigs[RTE_HASH_LOOKUP_BULK_MAX];
> + *idx = __builtin_ctzl(*lookup_mask);
> + if (*lookup_mask == 0)
> + *idx = 0;
>
> - RETURN_IF_TRUE(((h == NULL) || (keys == NULL) || (num_keys == 0) ||
> - (num_keys > RTE_HASH_LOOKUP_BULK_MAX) ||
> - (positions == NULL)), -EINVAL);
> + *primary_hash = rte_hash_hash(h, keys[*idx]);
> + *secondary_hash = rte_hash_secondary_hash(*primary_hash);
>
> - /* Get the hash signature and bucket index */
> - for (i = 0; i < num_keys; i++) {
> - sigs[i] = h->hash_func(keys[i], h->key_len,
> - h->hash_func_init_val) | h->sig_msb;
> - bucket_index = sigs[i] & h->bucket_bitmask;
> + *primary_hash |= h->sig_msb;
> +
> + *secondary_hash |= h->sig_msb;
> + *secondary_hash |= h->sig_secondary;
> +
> + *lookup_mask &= ~(1llu << *idx);
> +}
> +
> +
> +/* Lookup bulk stage 1: Prefetch primary/secondary buckets */
> +static inline void
> +lookup_stage1(uint64_t primary_hash, uint64_t secondary_hash,
> + const struct rte_hash_bucket **primary_bkt,
> + const struct rte_hash_bucket **secondary_bkt,
> + const struct rte_hash *h)
> +{
> + *primary_bkt = &h->buckets[primary_hash & h->bucket_bitmask];
> + *secondary_bkt = &h->buckets[secondary_hash & h->bucket_bitmask];
> +
> + rte_prefetch0(*primary_bkt);
> + rte_prefetch0(*secondary_bkt);
> +}
>
> - /* Pre-fetch relevant buckets */
> - rte_prefetch1((void *) get_sig_tbl_bucket(h, bucket_index));
> - rte_prefetch1((void *) get_key_tbl_bucket(h, bucket_index));
> +/*
> + * Lookup bulk stage 2: Search for match hashes in primary/secondary locations
> + * and prefetch first key slot
> + */
> +static inline void
> +lookup_stage2(unsigned idx, uint64_t primary_hash, uint64_t secondary_hash,
> + const struct rte_hash_bucket *primary_bkt,
> + const struct rte_hash_bucket *secondary_bkt,
> + const void **key_slot,
> + int32_t *positions,
> + uint64_t *extra_hits_mask,
> + const void *keys, const struct rte_hash *h)
> +{
> + unsigned primary_hash_matches, secondary_hash_matches, key_idx, i;
> + unsigned total_hash_matches;
> +
> + total_hash_matches = 1 << (RTE_HASH_BUCKET_ENTRIES * 2);
> + primary_hash_matches = 1 << RTE_HASH_BUCKET_ENTRIES;
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + primary_hash_matches |= ((primary_hash == primary_bkt->signatures[i]) << i);
> + total_hash_matches |= ((primary_hash == primary_bkt->signatures[i]) << i);
> }
>
> - /* Check if key is already present in the hash */
> - for (i = 0; i < num_keys; i++) {
> - bucket_index = sigs[i] & h->bucket_bitmask;
> - hash_sig_t *sig_bucket = get_sig_tbl_bucket(h, bucket_index);
> - uint8_t *key_bucket = get_key_tbl_bucket(h, bucket_index);
> -
> - positions[i] = -ENOENT;
> -
> - for (j = 0; j < h->bucket_entries; j++) {
> - if ((sigs[i] == sig_bucket[j]) &&
> - likely(memcmp(keys[i],
> - get_key_from_bucket(h, key_bucket, j),
> - h->key_len) == 0)) {
> - positions[i] = bucket_index *
> - h->bucket_entries + j;
> - break;
> - }
> - }
> + key_idx = primary_bkt->key_idx[__builtin_ctzl(primary_hash_matches)];
> +
> + secondary_hash_matches = 1 << RTE_HASH_BUCKET_ENTRIES;
> + for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
> + secondary_hash_matches |= ((secondary_hash == secondary_bkt->signatures[i]) << i);
> + total_hash_matches |= ((secondary_hash == secondary_bkt->signatures[i])
> + << (i + RTE_HASH_BUCKET_ENTRIES));
> + }
> +
> + if (key_idx == 0)
> + key_idx = secondary_bkt->key_idx[__builtin_ctzl(secondary_hash_matches)];
> +
> + *key_slot = (const char *)keys + key_idx * h->key_entry_size;
> +
> + rte_prefetch0(*key_slot);
> + positions[idx] = key_idx;
> +
> + *extra_hits_mask |= (uint64_t)(__builtin_popcount(primary_hash_matches) > 2) << idx;
> + *extra_hits_mask |= (uint64_t)(__builtin_popcount(secondary_hash_matches) > 2) << idx;
> + *extra_hits_mask |= (uint64_t)(__builtin_popcount(total_hash_matches) > 2) << idx;
> +
> +}
> +
> +
> +/* Lookup bulk stage 3: Check if key matches, update hit mask */
> +static inline void
> +lookup_stage3(unsigned idx, const void *key_slot,
> + const void * const *keys, int32_t *positions,
> + uint64_t *hits, const struct rte_hash *h)
> +{
> + unsigned hit;
> +
> + hit = !memcmp(key_slot, keys[idx], h->key_len);
> + if (unlikely(hit == 0))
> + positions[idx] = -ENOENT;
> + *hits = (uint64_t)(hit) << idx;
> +}
> +
> +static inline int
> +__rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
> + uint32_t num_keys, int32_t *positions) {
> +
> + uint64_t hits = 0;
> + uint64_t next_mask = 0;
> + uint64_t extra_hits_mask = 0;
> + uint64_t lookup_mask;
> + unsigned idx;
> + const void *key_store = h->key_store;
> +
> + unsigned idx00, idx01, idx10, idx11, idx20, idx21, idx30, idx31;
> + const struct rte_hash_bucket *primary_bkt10, *primary_bkt11;
> + const struct rte_hash_bucket *secondary_bkt10, *secondary_bkt11;
> + const struct rte_hash_bucket *primary_bkt20, *primary_bkt21;
> + const struct rte_hash_bucket *secondary_bkt20, *secondary_bkt21;
> + const void *k_slot20, *k_slot21, *k_slot30, *k_slot31;
> + uint64_t primary_hash00, primary_hash01;
> + uint64_t secondary_hash00, secondary_hash01;
> + uint64_t primary_hash10, primary_hash11;
> + uint64_t secondary_hash10, secondary_hash11;
> + uint64_t primary_hash20, primary_hash21;
> + uint64_t secondary_hash20, secondary_hash21;
> +
> + if (num_keys == RTE_HASH_LOOKUP_BULK_MAX)
> + lookup_mask = 0xffffffffffffffff;
> + else
> + lookup_mask = (1 << num_keys) - 1;
> +
> + lookup_stage0(&idx00, &lookup_mask, &primary_hash00,
> + &secondary_hash00, keys, h);
> + lookup_stage0(&idx01, &lookup_mask, &primary_hash01,
> + &secondary_hash01, keys, h);
> +
> + primary_hash10 = primary_hash00;
> + primary_hash11 = primary_hash01;
> + secondary_hash10 = secondary_hash00;
> + secondary_hash11 = secondary_hash01;
> + idx10 = idx00, idx11 = idx01;
> +
> + lookup_stage0(&idx00, &lookup_mask, &primary_hash00,
> + &secondary_hash00, keys, h);
> + lookup_stage0(&idx01, &lookup_mask, &primary_hash01,
> + &secondary_hash01, keys, h);
> + lookup_stage1(primary_hash10, secondary_hash10, &primary_bkt10,
> + &secondary_bkt10, h);
> + lookup_stage1(primary_hash11, secondary_hash11, &primary_bkt11,
> + &secondary_bkt11, h);
> +
> + primary_bkt20 = primary_bkt10;
> + primary_bkt21 = primary_bkt11;
> + secondary_bkt20 = secondary_bkt10;
> + secondary_bkt21 = secondary_bkt11;
> + primary_hash20 = primary_hash10;
> + primary_hash21 = primary_hash11;
> + secondary_hash20 = secondary_hash10;
> + secondary_hash21 = secondary_hash11;
> + idx20 = idx10, idx21 = idx11;
> + primary_hash10 = primary_hash00;
> + primary_hash11 = primary_hash01;
> + secondary_hash10 = secondary_hash00;
> + secondary_hash11 = secondary_hash01;
> + idx10 = idx00, idx11 = idx01;
> +
> + lookup_stage0(&idx00, &lookup_mask, &primary_hash00,
> + &secondary_hash00, keys, h);
> + lookup_stage0(&idx01, &lookup_mask, &primary_hash01,
> + &secondary_hash01, keys, h);
> + lookup_stage1(primary_hash10, secondary_hash10, &primary_bkt10,
> + &secondary_bkt10, h);
> + lookup_stage1(primary_hash11, secondary_hash11, &primary_bkt11,
> + &secondary_bkt11, h);
> + lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20,
> + secondary_bkt20, &k_slot20, positions, &extra_hits_mask,
> + key_store, h);
> + lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21,
> + secondary_bkt21, &k_slot21, positions, &extra_hits_mask,
> + key_store, h);
> +
> + while (lookup_mask) {
> + k_slot30 = k_slot20, k_slot31 = k_slot21;
> + idx30 = idx20, idx31 = idx21;
> + primary_bkt20 = primary_bkt10;
> + primary_bkt21 = primary_bkt11;
> + secondary_bkt20 = secondary_bkt10;
> + secondary_bkt21 = secondary_bkt11;
> + primary_hash20 = primary_hash10;
> + primary_hash21 = primary_hash11;
> + secondary_hash20 = secondary_hash10;
> + secondary_hash21 = secondary_hash11;
> + idx20 = idx10, idx21 = idx11;
> + primary_hash10 = primary_hash00;
> + primary_hash11 = primary_hash01;
> + secondary_hash10 = secondary_hash00;
> + secondary_hash11 = secondary_hash01;
> + idx10 = idx00, idx11 = idx01;
> +
> + lookup_stage0(&idx00, &lookup_mask, &primary_hash00,
> + &secondary_hash00, keys, h);
> + lookup_stage0(&idx01, &lookup_mask, &primary_hash01,
> + &secondary_hash01, keys, h);
> + lookup_stage1(primary_hash10, secondary_hash10, &primary_bkt10,
> + &secondary_bkt10, h);
> + lookup_stage1(primary_hash11, secondary_hash11, &primary_bkt11,
> + &secondary_bkt11, h);
> + lookup_stage2(idx20, primary_hash20, secondary_hash20,
> + primary_bkt20, secondary_bkt20, &k_slot20, positions,
> + &extra_hits_mask, key_store, h);
> + lookup_stage2(idx21, primary_hash21, secondary_hash21,
> + primary_bkt21, secondary_bkt21, &k_slot21, positions,
> + &extra_hits_mask, key_store, h);
> + lookup_stage3(idx30, k_slot30, keys, positions, &hits, h);
> + lookup_stage3(idx31, k_slot31, keys, positions, &hits, h);
> + }
> +
> + k_slot30 = k_slot20, k_slot31 = k_slot21;
> + idx30 = idx20, idx31 = idx21;
> + primary_bkt20 = primary_bkt10;
> + primary_bkt21 = primary_bkt11;
> + secondary_bkt20 = secondary_bkt10;
> + secondary_bkt21 = secondary_bkt11;
> + primary_hash20 = primary_hash10;
> + primary_hash21 = primary_hash11;
> + secondary_hash20 = secondary_hash10;
> + secondary_hash21 = secondary_hash11;
> + idx20 = idx10, idx21 = idx11;
> + primary_hash10 = primary_hash00;
> + primary_hash11 = primary_hash01;
> + secondary_hash10 = secondary_hash00;
> + secondary_hash11 = secondary_hash01;
> + idx10 = idx00, idx11 = idx01;
> + lookup_stage1(primary_hash10, secondary_hash10, &primary_bkt10,
> + &secondary_bkt10, h);
> + lookup_stage1(primary_hash11, secondary_hash11, &primary_bkt11,
> + &secondary_bkt11, h);
> + lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20,
> + secondary_bkt20, &k_slot20, positions, &extra_hits_mask,
> + key_store, h);
> + lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21,
> + secondary_bkt21, &k_slot21, positions, &extra_hits_mask,
> + key_store, h);
> + lookup_stage3(idx30, k_slot30, keys, positions, &hits, h);
> + lookup_stage3(idx31, k_slot31, keys, positions, &hits, h);
> +
> + k_slot30 = k_slot20, k_slot31 = k_slot21;
> + idx30 = idx20, idx31 = idx21;
> + primary_bkt20 = primary_bkt10;
> + primary_bkt21 = primary_bkt11;
> + secondary_bkt20 = secondary_bkt10;
> + secondary_bkt21 = secondary_bkt11;
> + primary_hash20 = primary_hash10;
> + primary_hash21 = primary_hash11;
> + secondary_hash20 = secondary_hash10;
> + secondary_hash21 = secondary_hash11;
> + idx20 = idx10, idx21 = idx11;
> +
> + lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20,
> + secondary_bkt20, &k_slot20, positions, &extra_hits_mask,
> + key_store, h);
> + lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21,
> + secondary_bkt21, &k_slot21, positions, &extra_hits_mask,
> + key_store, h);
> + lookup_stage3(idx30, k_slot30, keys, positions, &hits, h);
> + lookup_stage3(idx31, k_slot31, keys, positions, &hits, h);
> +
> + k_slot30 = k_slot20, k_slot31 = k_slot21;
> + idx30 = idx20, idx31 = idx21;
> +
> + lookup_stage3(idx30, k_slot30, keys, positions, &hits, h);
> + lookup_stage3(idx31, k_slot31, keys, positions, &hits, h);
> +
> + /* handle extra_hits_mask */
> + next_mask |= extra_hits_mask;
> +
> + /* ignore any items we have already found */
> + next_mask &= ~hits;
> +
> + if (unlikely(next_mask)) {
> + /* run a single search for each remaining item */
> + do {
> + idx = __builtin_ctzl(next_mask);
> + positions[idx] = rte_hash_lookup(h, keys[idx]);
> + next_mask &= ~(1llu << idx);
> + } while (next_mask);
> }
>
> return 0;
> }
> +
> +int
> +rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
> + uint32_t num_keys, int32_t *positions)
> +{
> + RETURN_IF_TRUE(((h == NULL) || (keys == NULL) || (num_keys == 0) ||
> + (num_keys > RTE_HASH_LOOKUP_BULK_MAX) ||
> + (positions == NULL)), -EINVAL);
> +
> + return __rte_hash_lookup_bulk(h, keys, num_keys, positions);
> +}
> diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h
> index 821a9d4..4088ac4 100644
> --- a/lib/librte_hash/rte_hash.h
> +++ b/lib/librte_hash/rte_hash.h
> @@ -1,7 +1,7 @@
> /*-
> * BSD LICENSE
> *
> - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
> * All rights reserved.
> *
> * Redistribution and use in source and binary forms, with or without
> @@ -42,27 +42,36 @@
>
> #include <stdint.h>
> #include <sys/queue.h>
> +#include <rte_ring.h>
The depdirs in the makefile needs to be updated with a new dependency on
rte_ring library.
>
> #ifdef __cplusplus
> extern "C" {
> #endif
>
> /** Maximum size of hash table that can be created. */
> -#define RTE_HASH_ENTRIES_MAX (1 << 26)
> +#define RTE_HASH_ENTRIES_MAX (1 << 30)
>
> -/** Maximum bucket size that can be created. */
> -#define RTE_HASH_BUCKET_ENTRIES_MAX 16
This is a public macro, you can't just drop it. I suggest changing it's value
to 4, and adding the new macro below alongside it. If you want, you can
also see about marking it as deprecated to remove in future, but I'm not sure
it's worthwhile doing so.
> +/** Number of items per bucket. */
> +#define RTE_HASH_BUCKET_ENTRIES 4
>
> /** Maximum length of key that can be used. */
> #define RTE_HASH_KEY_LENGTH_MAX 64
>
> -/** Max number of keys that can be searched for using rte_hash_lookup_multi. */
> -#define RTE_HASH_LOOKUP_BULK_MAX 16
> -#define RTE_HASH_LOOKUP_MULTI_MAX RTE_HASH_LOOKUP_BULK_MAX
As above, you need to keep the lookup_multi_max macro.
> -
> -/** Max number of characters in hash name.*/
> +/** Maximum number of characters in hash name.*/
> #define RTE_HASH_NAMESIZE 32
>
> +/** Bits that will be right shifted when calculating a secondary hash. */
> +#define RTE_HASH_ALT_BITS_SHIFT 12
> +
> +/** Bits that will be XORed to obtained a secondary hash. */
> +#define RTE_HASH_ALT_BITS_XOR_MASK 0x5bd1e995
If these macros are for use internally in the hash implementation only, mark
them as @internal, so that people don't start depending on them in their apps.
This allows us to rename them or remove them in future if we like, without having
to give one-releases deprecation warning.
> +
> +/** Maximum number of keys that can be searched for using rte_hash_lookup_bulk. */
> +#define RTE_HASH_LOOKUP_BULK_MAX 64
> +
> +/* Stored key size is a multiple of this value */
> +#define KEY_ALIGNMENT 16
> +
> /** Signature of key that is stored internally. */
> typedef uint32_t hash_sig_t;
>
> @@ -77,9 +86,9 @@ typedef uint32_t (*rte_hash_function)(const void *key, uint32_t key_len,
> struct rte_hash_parameters {
> const char *name; /**< Name of the hash. */
> uint32_t entries; /**< Total hash table entries. */
> - uint32_t bucket_entries; /**< Bucket entries. */
> - uint32_t key_len; /**< Length of hash key. */
> - rte_hash_function hash_func; /**< Function used to calculate hash. */
> + uint32_t bucket_entries; /**< Bucket entries. */
> + uint16_t key_len; /**< Length of hash key. */
> + rte_hash_function hash_func; /**< Primary Hash function used to calculate hash. */
> uint32_t hash_func_init_val; /**< Init value used by hash_func. */
> int socket_id; /**< NUMA Socket ID for memory. */
> };
Due to padding of the uint16_t value, I don't think this will break the ABI.
However, it might be worthwhile manually putting in an explicit pad (or comment)
to make this clear.
> @@ -88,24 +97,35 @@ struct rte_hash_parameters {
> struct rte_hash {
As part of this patchset, it might be worthwhile updating the comment on
struct rte_hash to indicate that this is an internal data-structure that should
not be directly referenced by apps.
> char name[RTE_HASH_NAMESIZE]; /**< Name of the hash. */
> uint32_t entries; /**< Total table entries. */
> - uint32_t bucket_entries; /**< Bucket entries. */
> - uint32_t key_len; /**< Length of hash key. */
> + uint32_t bucket_entries; /**< Bucket entries. */
> + uint16_t key_len; /**< Length of hash key. */
> rte_hash_function hash_func; /**< Function used to calculate hash. */
> uint32_t hash_func_init_val; /**< Init value used by hash_func. */
> uint32_t num_buckets; /**< Number of buckets in table. */
> uint32_t bucket_bitmask; /**< Bitmask for getting bucket index
> from hash signature. */
> - hash_sig_t sig_msb; /**< MSB is always set in valid signatures. */
> - uint8_t *sig_tbl; /**< Flat array of hash signature buckets. */
> - uint32_t sig_tbl_bucket_size; /**< Signature buckets may be padded for
> - alignment reasons, and this is the
> - bucket size used by sig_tbl. */
> - uint8_t *key_tbl; /**< Flat array of key value buckets. */
> - uint32_t key_tbl_key_size; /**< Keys may be padded for alignment
> - reasons, and this is the key size
> - used by key_tbl. */
> + uint16_t key_entry_size; /**< Size of each key entry. */
> + int socket_id; /**< NUMA Socket ID for memory. */
> + uint64_t sig_msb; /**< MSB is always set in valid signatures. */
> + uint64_t sig_secondary; /**< Second MSB is set when hash is calculated
> + from secondary hash function. */
> +
> + struct rte_ring *free_slots; /**< Ring that stores all indexes
> + of the free slots in the key table */
> + void *key_store; /**< Table storing all keys and data */
> +
> + struct rte_hash_bucket *buckets; /**< Table with buckets storing all the
> + hash values and key indexes
> + to the key table*/
> };
Since this header file does not contain any inline functions that operate on
this structure, it can be safely moved to the .c file, and replaced by a simple
"struct rte_hash" definition.
>
> +/** Bucket structure */
> +struct rte_hash_bucket {
> + uint64_t signatures[RTE_HASH_BUCKET_ENTRIES];
> + uint32_t key_idx[RTE_HASH_BUCKET_ENTRIES];
> +} __rte_cache_aligned;
> +
Move to .c file as unused in this file.
> +
> /**
> * Create a new hash table.
> *
> @@ -126,7 +146,6 @@ struct rte_hash {
> struct rte_hash *
> rte_hash_create(const struct rte_hash_parameters *params);
>
> -
> /**
> * Find an existing hash table object and return a pointer to it.
> *
> @@ -158,9 +177,9 @@ rte_hash_free(struct rte_hash *h);
> * Key to add to the hash table.
> * @return
> * - -EINVAL if the parameters are invalid.
> + * - -EAGAIN if key could not be added (table needs rehash)
> * - -ENOSPC if there is no space in the hash for this key.
> - * - A positive value that can be used by the caller as an offset into an
> - * array of user data. This value is unique for this key.
> + * - 0 if key was added successfully
> */
This is an ABI and API change. With this change you can no longer use the old-style
way of returning indexes to allow the app to store the data locally.
> int32_t
> rte_hash_add_key(const struct rte_hash *h, const void *key);
> @@ -177,13 +196,12 @@ rte_hash_add_key(const struct rte_hash *h, const void *key);
> * Hash value to add to the hash table.
> * @return
> * - -EINVAL if the parameters are invalid.
> + * - -EAGAIN if key could not be added (table needs rehash)
> * - -ENOSPC if there is no space in the hash for this key.
> - * - A positive value that can be used by the caller as an offset into an
> - * array of user data. This value is unique for this key.
> + * - 0 if key was added successfully
> */
> int32_t
> -rte_hash_add_key_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig);
> +rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig);
>
> /**
> * Remove a key from an existing hash table. This operation is not multi-thread
> @@ -196,9 +214,7 @@ rte_hash_add_key_with_hash(const struct rte_hash *h,
> * @return
> * - -EINVAL if the parameters are invalid.
> * - -ENOENT if the key is not found.
> - * - A positive value that can be used by the caller as an offset into an
> - * array of user data. This value is unique for this key, and is the same
> - * value that was returned when the key was added.
> + * - 0 if key was deleted successfully
> */
> int32_t
> rte_hash_del_key(const struct rte_hash *h, const void *key);
> @@ -216,14 +232,10 @@ rte_hash_del_key(const struct rte_hash *h, const void *key);
> * @return
> * - -EINVAL if the parameters are invalid.
> * - -ENOENT if the key is not found.
> - * - A positive value that can be used by the caller as an offset into an
> - * array of user data. This value is unique for this key, and is the same
> - * value that was returned when the key was added.
> + * - 0 if key was deleted successfully
> */
> int32_t
> -rte_hash_del_key_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig);
> -
> +rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig);
>
> /**
> * Find a key in the hash table. This operation is multi-thread safe.
> @@ -235,9 +247,7 @@ rte_hash_del_key_with_hash(const struct rte_hash *h,
> * @return
> * - -EINVAL if the parameters are invalid.
> * - -ENOENT if the key is not found.
> - * - A positive value that can be used by the caller as an offset into an
> - * array of user data. This value is unique for this key, and is the same
> - * value that was returned when the key was added.
> + * - 0 if key was found successfully
> */
> int32_t
> rte_hash_lookup(const struct rte_hash *h, const void *key);
> @@ -254,14 +264,40 @@ rte_hash_lookup(const struct rte_hash *h, const void *key);
> * @return
> * - -EINVAL if the parameters are invalid.
> * - -ENOENT if the key is not found.
> - * - A positive value that can be used by the caller as an offset into an
> - * array of user data. This value is unique for this key, and is the same
> - * value that was returned when the key was added.
> + * - 0 if key was found successfully
> */
> int32_t
> -rte_hash_lookup_with_hash(const struct rte_hash *h,
> - const void *key, hash_sig_t sig);
> +rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig);
>
> +#define rte_hash_lookup_multi rte_hash_lookup_bulk
> +/**
> + * Find multiple keys in the hash table. This operation is multi-thread safe.
> + *
> + * @param h
> + * Hash table to look in.
> + * @param keys
> + * A pointer to a list of keys to look for.
> + * @param num_keys
> + * How many keys are in the keys list (less than RTE_HASH_LOOKUP_BULK_MAX).
> + * @param positions
> + * Output containing a list of values, corresponding to the list of keys that
> + * can be used by the caller as an offset into an array of user data. These
> + * values are unique for each key, and are the same values that were returned
> + * when each key was added. If a key in the list was not found, then -ENOENT
> + * will be the value.
> + * @return
> + * -EINVAL if there's an error, otherwise number of hits.
> + */
> +int
> +rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
> + uint32_t num_keys, int32_t *positions);
> +
> +static inline hash_sig_t
> +hash_alt(const uint32_t primary_hash) {
> + uint32_t tag = primary_hash >> RTE_HASH_ALT_BITS_SHIFT;
> +
> + return (primary_hash ^ ((tag + 1) * RTE_HASH_ALT_BITS_XOR_MASK));
> +}
This needs a doxygen comment, is it public or internal?
>
> /**
> * Calc a hash value by key. This operation is not multi-process safe.
> @@ -280,28 +316,23 @@ rte_hash_hash(const struct rte_hash *h, const void *key)
> return h->hash_func(key, h->key_len, h->hash_func_init_val);
> }
>
> -#define rte_hash_lookup_multi rte_hash_lookup_bulk
> /**
> - * Find multiple keys in the hash table. This operation is multi-thread safe.
> + * Calc the secondary hash value by key. This operation is not multi-process safe.
> *
> * @param h
> * Hash table to look in.
> - * @param keys
> - * A pointer to a list of keys to look for.
> - * @param num_keys
> - * How many keys are in the keys list (less than RTE_HASH_LOOKUP_BULK_MAX).
> - * @param positions
> - * Output containing a list of values, corresponding to the list of keys that
> - * can be used by the caller as an offset into an array of user data. These
> - * values are unique for each key, and are the same values that were returned
> - * when each key was added. If a key in the list was not found, then -ENOENT
> - * will be the value.
> + * @param key
> + * Key to find.
> * @return
> - * -EINVAL if there's an error, otherwise 0.
> + * - hash value
> */
> -int
> -rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
> - uint32_t num_keys, int32_t *positions);
> +static inline hash_sig_t
> +rte_hash_secondary_hash(const uint32_t primary_hash)
> +{
> + /* calc hash result by key */
> + return hash_alt(primary_hash);
> +}
> +
> #ifdef __cplusplus
> }
> #endif
> --
> 2.4.2
>
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 10:35 9% ` Neil Horman
2015-06-17 11:06 4% ` Richardson, Bruce
2015-06-17 12:14 7% ` Panu Matilainen
@ 2015-06-18 8:36 4% ` Zhang, Helin
2 siblings, 0 replies; 200+ results
From: Zhang, Helin @ 2015-06-18 8:36 UTC (permalink / raw)
To: Neil Horman, Thomas Monjalon; +Cc: dev
Hi Neil
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> Sent: Wednesday, June 17, 2015 6:35 PM
> To: Thomas Monjalon
> Cc: announce@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-announce] important design choices - statistics -
> ABI
>
> On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> > Hi all,
> >
> > Sometimes there are some important discussions about architecture or
> > design which require opinions from several developers. Unfortunately,
> > we cannot read every threads. Maybe that using the announce mailing
> > list will help to bring more audience to these discussions.
> > Please note that
> > - the announce@ ML is moderated to keep a low traffic,
> > - every announce email is forwarded to dev@ ML.
> > In case you want to reply to this email, please use dev@dpdk.org address.
> >
> > There were some debates about software statistics disabling.
> > Should they be always on or possibly disabled when compiled?
> > We need to take a decision shortly and discuss (or agree) this proposal:
> > http://dpdk.org/ml/archives/dev/2015-June/019461.html
> >
> > During the development of the release 2.0, there was an agreement to
> > keep ABI compatibility or to bring new ABI while keeping old one during one
> release.
> > In case it's not possible to have this transition, the (exceptional)
> > break should be acknowledged by several developers.
> > http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
> > There were some interesting discussions but not a lot of participants:
> >
> > http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus=84
> > 61
> >
> > During the current development cycle for the release 2.1, the ABI
> > question arises many times in different threads.
> > To add the hash key size field, it is proposed to use a struct padding gap:
> > http://dpdk.org/ml/archives/dev/2015-June/019386.html
> > To support the flow director for VF, there is no proposal yet:
> > http://dpdk.org/ml/archives/dev/2015-June/019343.html
> > To add the speed capability, it is proposed to break ABI in the release 2.2:
> > http://dpdk.org/ml/archives/dev/2015-June/019225.html
> > To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
> > http://dpdk.org/ml/archives/dev/2015-June/019443.html
> > To add the interrupt mode, it is proposed to add a build-time option
> > CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking
> binary:
> > http://dpdk.org/ml/archives/dev/2015-June/018947.html
> > To add the packet type, there is a proposal to add a build-time option
> > CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
> > http://dpdk.org/ml/archives/dev/2015-June/019172.html
> > We must also better document how to remove a deprecated ABI:
> > http://dpdk.org/ml/archives/dev/2015-June/019465.html
> > The ABI compatibility is a new constraint and we need to better
> > understand what it means and how to proceed. Even the macros are not yet
> well documented:
> > http://dpdk.org/ml/archives/dev/2015-June/019357.html
> >
> > Thanks for your attention and your participation in these important choices.
> >
>
> Thomas-
> Just to re-iterate what you said earlier, and what was discussed in the
> previous ABI discussions
>
> 1) ABI stability was introduced to promote DPDK's ability to be included with
> various linux and BSD distributions. Distributions, by and large, favor building
> libraries as DSO's, favoring security and updatability in favor of all out
> performance.
>
> 2) The desire was to put DPDK developers in a mindset whereby ABI stability was
> something they needed to think about during development, as the DPDK
> exposes many data structures and instances that cannot be changed without
> breaking ABI
>
> 3) The versioning mechanism was introduced to allow for backward compatibility
> during periods in which we needed to support both an old an new ABI
>
> 4) As Stephan and others point out, its not expected that we will always be able
> to maintain ABI, and as such an easy library versioning mechanism was
> introduced to prevent the loading of an incompatible library with an older
> application
>
> 5) The ABI policy was introduced to create a method by which new ABI facets
> could be scheduled while allowing distros to prepare their downstream users for
> the upcomming changes.
>
>
> It seems to me, looking back over these last few months, that we're falling down
> a bit on our use of (3). I've seen several people take advantage of the ABI
> scheduled updates, but no one has tried the versioning interface, and as a result
> patches are getting delayed, which was never my intent. Not sure whats to be
> done about that, but we should probably address it. Is use of the versionnig
> interface just too hard or convoluted?
That means we should try to use versioning mechanism as more as possible?
Are there any rules/instructions to judge what type of changes we should try
versioning mechanism, and what else we shouldn't try?
Is there any good examples of using versioning mechanism for reference?
Even not in DPDK project.
Thanks,
Helin
>
> Neil
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [PATCH v7 0/4] User-space Ethtool
@ 2015-06-18 2:04 3% ` Stephen Hemminger
2015-06-18 12:47 0% ` Wang, Liang-min
0 siblings, 1 reply; 200+ results
From: Stephen Hemminger @ 2015-06-18 2:04 UTC (permalink / raw)
To: Liang-Min Larry Wang; +Cc: dev
On Wed, Jun 17, 2015 at 6:22 PM, Liang-Min Larry Wang <
liang-min.wang@intel.com> wrote:
> This implementation is designed to provide a familar interface for
> applications that rely on kernel-space driver to support ethtool_op and
> net_device_op for device management. The initial implementation focuses on
> ops that can be implemented through existing netdev APIs. More ops will be
> supported in latter release.
>
> v7 change:
> - Remove rte_eth_dev_get_ringparam implementation
> v6 change:
> - Rebase to match new changes over librte_ether
> v5 change:
> - Change API name from 'leng' to 'length'
> - Remove unused data structure rte_dev_vf_info
> - Remove placeholder API rte_eth_dev_set_ringparam
> - Clean up set_mac_addr implementation
> v4 change:
> - Add rte_eth_xxx apis and respective ops over igb and ixgbe
> to support ethtool and net device alike ops
> - Add an example to demonstrate the use of ethtool library
> v3 change:
> - Fix a build issue
> v2 change:
> - Implement rte_eth_dev_default_mac_addr_set through dev_ops::mac_addr_set
> so it would support NIC devices other than ixgbe and igb
>
> Liang-Min Larry Wang (4):
> ethdev: add apis to support access device info
> ixgbe: add ops to support ethtool ops
> igb: add ops to support ethtool ops
> examples: new example: l2fwd-ethtool
>
> drivers/net/e1000/igb_ethdev.c | 186 ++++
> drivers/net/e1000/igb_regs.h | 217 +++++
> drivers/net/ixgbe/ixgbe_ethdev.c | 183 ++++
> drivers/net/ixgbe/ixgbe_regs.h | 357 ++++++++
> examples/l2fwd-ethtool/Makefile | 55 ++
> examples/l2fwd-ethtool/l2fwd-app/Makefile | 58 ++
> examples/l2fwd-ethtool/l2fwd-app/main.c | 1030
> ++++++++++++++++++++++
> examples/l2fwd-ethtool/l2fwd-app/netdev_api.h | 781 ++++++++++++++++
> examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h | 151 ++++
> examples/l2fwd-ethtool/lib/Makefile | 55 ++
> examples/l2fwd-ethtool/lib/rte_ethtool.c | 301 +++++++
> examples/l2fwd-ethtool/lib/rte_ethtool.h | 378 ++++++++
> examples/l2fwd-ethtool/nic-control/Makefile | 55 ++
> examples/l2fwd-ethtool/nic-control/nic_control.c | 412 +++++++++
> lib/librte_ether/Makefile | 1 +
> lib/librte_ether/rte_eth_dev_info.h | 57 ++
> lib/librte_ether/rte_ethdev.c | 115 +++
> lib/librte_ether/rte_ethdev.h | 117 +++
> lib/librte_ether/rte_ether_version.map | 6 +
> 19 files changed, 4515 insertions(+)
> create mode 100644 drivers/net/e1000/igb_regs.h
> create mode 100644 drivers/net/ixgbe/ixgbe_regs.h
> create mode 100644 examples/l2fwd-ethtool/Makefile
> create mode 100644 examples/l2fwd-ethtool/l2fwd-app/Makefile
> create mode 100644 examples/l2fwd-ethtool/l2fwd-app/main.c
> create mode 100644 examples/l2fwd-ethtool/l2fwd-app/netdev_api.h
> create mode 100644 examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h
> create mode 100644 examples/l2fwd-ethtool/lib/Makefile
> create mode 100644 examples/l2fwd-ethtool/lib/rte_ethtool.c
> create mode 100644 examples/l2fwd-ethtool/lib/rte_ethtool.h
> create mode 100644 examples/l2fwd-ethtool/nic-control/Makefile
> create mode 100644 examples/l2fwd-ethtool/nic-control/nic_control.c
> create mode 100644 lib/librte_ether/rte_eth_dev_info.h
>
> --
> 2.1.4
>
>
I agree with having a more complete API, but have some nits to pick.
Could the API be more abstract to reduce ABI issues in future?
I know choosing names is hard, but as a Linux developer ethtool has a very
specific meaning to me.
This API encompasses things broader than Linux ethtool and has different
semantics therefore
not sure having something in DPDK with same name is really a good idea.
It would be better to call it something else like netdev_?? Or dpnet_??
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] rte_mbuf.next in 2nd cacheline
[not found] ` <2601191342CEEE43887BDE71AB97725836A1237C@irsmsx105.ger.corp.intel.com>
@ 2015-06-17 18:50 3% ` Ananyev, Konstantin
0 siblings, 0 replies; 200+ results
From: Ananyev, Konstantin @ 2015-06-17 18:50 UTC (permalink / raw)
To: dev
Hi Dave,
> From: Dave Barach (dbarach) [mailto:dbarach@cisco.com]
> Sent: Wednesday, June 17, 2015 4:46 PM
> To: Venkatesan, Venky; Richardson, Bruce; olivier.matz@6wind.com; Ananyev, Konstantin
> Cc: Damjan Marion (damarion)
> Subject: RE: [dpdk-dev] rte_mbuf.next in 2nd cacheline
>
> Dear Venky,
>
> The first thing I noticed - on a specific piece of hardware, yadda yadda yadda - was that the i40e driver speed-path spent an ungodly
> amount of time stalled in i40e_rx_alloc_bufs(.) in rte_mbuf_refcnt_set. Mumble, missing prefetch. I added a stride-of-1 prefetch,
> which made the first stall go away. See below.
>
> Next thing I noticed: a stall setting mb->next = 0, in the non-scattered RX case. So I added the (commented-out) rte_prefetch0
> (&pfmb->next). At that point, I decided to move the buffer metadata around to eliminate the second prefetch.
>
> Taken together, these changes made a 10% PPS difference, again in a specific use case.
That seems like a valid point, but why moving next to the first cache-line is considered as the only possible option?
As Bruce suggested before, we can try to get rid of touching next in non-scattered RX routines.
That I think should provide similar performance improvement for i40e/ixgbe fast-path scalar RX code.
Or you are talking about hit in your app layer code, when you start chain mbufs together?
>
> Damjan was going to produce a cleaned up version of the rte_mbuf.h diffs, of the form:
>
> struct rte_mbuf {
> #ifdef CONFIG_OFFLOAD_IN_FIRST_CACHE_LINE
> Offload-in-first-cache-line;
> Next-in-second-cache-line;
> #else
> Offload-in-second-cache-line;
> Next-in-first-cache-line;r
> #endif
> };
>
> .along with a parallel change in the kernel module version.
As first, with the proposed below changes ixgbe vector RX routine would be broken.
Of course, it could be fixed by putting even more conditional compilation around -
enable vector RX, only when OFFLOAD_IN_FIRST_CACHE_LINE enabled, etc.
Second, how long it would take before someone else would like to introduce another mbuf fields swap?
All for perfectly good reason of course.
Let say, swap 'hash' and 'segn' (to keep vector RX working),
or 'next' and 'userdata', or put tx_offload into the first line (traffic generators).
I think if we'll go that way (allow mbuf fields swapping at build-time) we'll end up with
totally unmaintainable code.
Not to mention problems with ABI compatibility) (shared libraries, multiple processes, KNI).
So, I think we better stick with one mbuf format.
If it's absolutely necessary to move next into the first cache, I think it has to be done for all configs.
Though, from what you described with i40e_rx_alloc_bufs() -
that looks like a flaw in particular implementation, that might be fixed without changing mbuf format.
>
> I'm out of LSU bandwidth / prefetch slots in a number of apps - mostly L2 apps - which will never use h/w offload results. I can see
> your point about not turning dpdk buffer metadata into a garbage can. On the other hand, the problems we face often involve MTU
> => scattered RX, with a mix of small and large packets. As in: enough PPS to care about extra cache-line fills.
>
> Hope this explains it a bit. We can obviously make these changes in our own repos, but I can't imagine that we're the only folks who
> might not use h/w offload results.
>
> Thanks. Dave
>
>
> diff --git a/lib/librte_pmd_i40e/i40e_rxtx.c b/lib/librte_pmd_i40e/i40e_rxtx.c
> index 9c7be6f..1200361 100644
> --- a/lib/librte_pmd_i40e/i40e_rxtx.c
> +++ b/lib/librte_pmd_i40e/i40e_rxtx.c
> @@ -779,9 +779,15 @@ i40e_rx_alloc_bufs(struct i40e_rx_queue *rxq)
>
> rxdp = &rxq->rx_ring[alloc_idx];
> for (i = 0; i < rxq->rx_free_thresh; i++) {
> + if (i < (rxq->rx_free_thresh - 1)) {
> + struct rte_mbuf *pfmb;
> + pfmb = rxep[i+1].mbuf;
> + rte_prefetch0 (pfmb);
> + // rte_prefetch0 (&pfmb->next);
Wonder does your compiler unroll that loop?
If not, wonder, would manually unrolling it (by 4 or so) help?
Konstantin
> + }
> mb = rxep[i].mbuf;
> rte_mbuf_refcnt_set(mb, 1);
> - mb->next = NULL;
> + mb->next = NULL; /* $$$ in second cacheline */
> mb->data_off = RTE_PKTMBUF_HEADROOM;
> mb->nb_segs = 1;
> mb->port = rxq->port_id;
>
>
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> index 55749bc..efd7f4e 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -288,6 +288,12 @@ struct rte_mbuf {
> uint32_t pkt_len; /**< Total pkt len: sum of all segments. */
> uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */
> uint16_t reserved;
> + uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */
> +
> + struct rte_mbuf *next; /**< Next segment of scattered packet. */
> +
> + /* second cache line - fields only used in slow path or on TX */
> + MARKER cacheline1 __rte_cache_aligned;
> union {
> uint32_t rss; /**< RSS hash result if RSS enabled */
> struct {
> @@ -307,18 +313,12 @@ struct rte_mbuf {
> uint32_t usr; /**< User defined tags. See rte_distributor_process() */
> } hash; /**< hash information */
>
> - uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */
> -
> - /* second cache line - fields only used in slow path or on TX */
> - MARKER cacheline1 __rte_cache_aligned;
> -
> union {
> void *userdata; /**< Can be used for external metadata */
> uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */
> };
>
> struct rte_mempool *pool; /**< Pool from which mbuf was allocated. */
> - struct rte_mbuf *next; /**< Next segment of scattered packet. */
>
> /* fields to support TX offloads */
> union {
>
>
>
>
> Thanks. Dave
>
> From: Venkatesan, Venky [mailto:venky.venkatesan@intel.com]
> Sent: Wednesday, June 17, 2015 11:03 AM
> To: Richardson, Bruce; Dave Barach (dbarach); olivier.matz@6wind.com; Ananyev, Konstantin
> Cc: Damjan Marion (damarion)
> Subject: RE: [dpdk-dev] rte_mbuf.next in 2nd cacheline
>
> Dave,
>
> Is there a patch that I can look at? From your description what you seem to indicate is that the mbuf structure becomes variant
> between applications - that to me is likely a non-starter. If rte_mbuf is variant between implementations, then we really have no
> commonality that all VNFs can rely on.
>
> I may be getting a bit ahead of things here but letting different apps implement different mbuf layouts means, to achieve any level of
> commonality for upper level apps we need to go to accessor functions (not inline macros) to get various components - pretty much
> like ODP does; all that does is add function call overhead per access and that is completely non-performant. We toyed with that about
> 5 years ago and tossed it out.
>
> Bruce,
>
> To some extent I need to get an understanding of why this performance drop is actually happening. Since SNB we have had a paired
> cache line prefetcher that brings in the cache line pair. I think the reason that we have the perf issue is that half the mbufs actually
> begin on an odd cache line boundary - i.e. those are the ones that will suffer a cache miss on rte_mbuf.next. Could you verify that this
> is the case, and see what happens if we address all mbufs beginning on an even cache line? That runs into another potential issue with
> 4K aliasing, but I may have a way to avoid that.
>
> Regards,
> -Venky
>
>
> From: Richardson, Bruce
> Sent: Wednesday, June 17, 2015 7:50 AM
> To: Dave Barach (dbarach); olivier.matz@6wind.com; Ananyev, Konstantin
> Cc: Damjan Marion (damarion); Venkatesan, Venky
> Subject: RE: [dpdk-dev] rte_mbuf.next in 2nd cacheline
>
> Hi,
>
> it's something we can look at - especially once we see the proposed patch.
>
> However, my question is, if an app is cycle constrained such that the extra cache-line reference for jumbo frames cause a problem, is
> that app not likely to really suffer performance issues when run with smaller e.g. 256 byte packet sizes? And in the inverse case, if an
> app can deal with small packets, is it not likely able to take the extra hit for the jumbo frames? This was our thinking when doing the
> cache-line split, but perhaps the logic doesn't hold up in the cases you refer to.
>
> Regards,
> /Bruce
>
> From: Dave Barach (dbarach) [mailto:dbarach@cisco.com]
> Sent: Wednesday, June 17, 2015 3:37 PM
> To: Richardson, Bruce; olivier.matz@6wind.com; Ananyev, Konstantin
> Cc: Damjan Marion (damarion)
> Subject: RE: [dpdk-dev] rte_mbuf.next in 2nd cacheline
>
> Dear Bruce,
>
> We've implemented a number of use cases which can't or at least don't currently use hardware offload data. Examples: L2 bridging,
> integrated routing and bridging, various flavors of tunneling, ipv6 MAP, ipv6 segment routing, and so on.
>
> You're not considering the cost of additional pressure on the load-store unit, memory system, caused when mb->next must be
> prefetched, set, and cleared. It doesn't matter that the packets are large, the cost still exists. As we transition to 40 and 100g NICs,
> large-packet PPS-per-core becomes more of an issue.
>
> Damjan has offered to make the layout of the buffer metadata configurable, so that folks can "have it their way." Given that it's a ~10
> line change - with minimal comedic potential - it seems like a reasonable way to go.
>
> Thoughts?
>
> Thanks. Dave Barach
> Cisco Fellow
>
> From: Damjan Marion (damarion)
> Sent: Wednesday, June 17, 2015 10:17 AM
> To: Dave Barach (dbarach)
> Subject: Fwd: [dpdk-dev] rte_mbuf.next in 2nd cacheline
>
>
>
> Begin forwarded message:
>
> From: Bruce Richardson <bruce.richardson@intel.com>
> Subject: Re: [dpdk-dev] rte_mbuf.next in 2nd cacheline
> Date: 17 Jun 2015 16:06:48 CEST
> To: "Damjan Marion (damarion)" <damarion@cisco.com>
> Cc: Olivier MATZ <olivier.matz@6wind.com>, "Ananyev, Konstantin" <konstantin.ananyev@intel.com>, "dev@dpdk.org"
> <dev@dpdk.org>
>
> On Wed, Jun 17, 2015 at 01:55:57PM +0000, Damjan Marion (damarion) wrote:
>
> On 15 Jun 2015, at 16:12, Bruce Richardson <bruce.richardson@intel.com> wrote:
>
> The next pointers always start out as NULL when the mbuf pool is created. The
> only time it is set to non-NULL is when we have chained mbufs. If we never have
> any chained mbufs, we never need to touch the next field, or even read it - since
> we have the num-segments count in the first cache line. If we do have a multi-segment
> mbuf, it's likely to be a big packet, so we have more processing time available
> and we can then take the hit of setting the next pointer.
>
> There are applications which are not using rx offload, but they deal with chained mbufs.
> Why they are less important than ones using rx offload? This is something people
> should be able to configure on build time.
>
> It's not that they are less important, it's that the packet processing cycle count
> budget is going to be greater. A packet which is 64 bytes, or 128 bytes in size
> can make use of a number of RX offloads to reduce it's processing time. However,
> a 64/128 packet is not going to be split across multiple buffers [unless we
> are dealing with a very unusual setup!].
>
> To handle 64 byte packets at 40G line rate, one has 50 cycles per core per packet
> when running at 3GHz. [3000000000 cycles / 59.5 mpps].
> If we assume that we are dealing with fairly small buffers
> here, and that anything greater than 1k packets are chained, we still have 626
> cycles per 3GHz core per packet to work with for that 1k packet. Given that
> "normal" DPDK buffers are 2k in size, we have over a thousand cycles per packet
> for any packet that is split.
>
> In summary, packets spread across multiple buffers are large packets, and so have
> larger packet cycle count budgets and so can much better absorb the cost of
> touching a second cache line in the mbuf than a 64-byte packet can. Therefore,
> we optimize for the 64B packet case.
>
> Hope this clarifies things a bit.
>
> Regards,
> /Bruce
^ permalink raw reply [relevance 3%]
* [dpdk-dev] [PATCH 1/5] ethdev: add new API to retrieve RX/TX queue information
@ 2015-06-17 16:54 3% ` Konstantin Ananyev
0 siblings, 1 reply; 200+ results
From: Konstantin Ananyev @ 2015-06-17 16:54 UTC (permalink / raw)
To: dev
Add the ability for the upper layer to query RX/TX queue information.
Add new structures:
struct rte_eth_rx_qinfo
struct rte_eth_tx_qinfo
new functions:
rte_eth_rx_queue_info_get
rte_eth_tx_queue_info_get
into rte_etdev API.
Left extra free space in the qinfo structures,
so extra fields could be added later without ABI breakage.
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
lib/librte_ether/rte_ethdev.c | 48 +++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 77 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 124 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e13fde5..6b9a7ef 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3629,6 +3629,54 @@ rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id,
}
int
+rte_eth_rx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_rx_qinfo *qinfo)
+{
+ struct rte_eth_dev *dev;
+
+ memset(qinfo, 0, sizeof(*qinfo));
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ if (queue_id >= dev->data->nb_rx_queues) {
+ PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id);
+ return -EINVAL;
+ }
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_qinfo_get, -ENOTSUP);
+ dev->dev_ops->rx_qinfo_get(dev, queue_id, qinfo);
+ return 0;
+}
+
+int
+rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_tx_qinfo *qinfo)
+{
+ struct rte_eth_dev *dev;
+
+ memset(qinfo, 0, sizeof(*qinfo));
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+ return -EINVAL;
+ }
+
+ dev = &rte_eth_devices[port_id];
+ if (queue_id >= dev->data->nb_tx_queues) {
+ PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id);
+ return -EINVAL;
+ }
+
+ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_qinfo_get, -ENOTSUP);
+ dev->dev_ops->tx_qinfo_get(dev, queue_id, qinfo);
+ return 0;
+}
+
+int
rte_eth_dev_set_mc_addr_list(uint8_t port_id,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 04c192d..45afdd3 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -942,6 +942,30 @@ struct rte_eth_xstats {
uint64_t value;
};
+/**
+ * Ethernet device RX queue information strcuture.
+ * Used to retieve information about configured queue.
+ */
+struct rte_eth_rx_qinfo {
+ struct rte_mempool *mp; /**< mempool used by that queue. */
+ struct rte_eth_rxconf conf; /**< queue config parameters. */
+ uint8_t scattered_rx; /**< scattered packets RX supported. */
+ uint16_t nb_desc; /**< configured number of RXDs. */
+ uint16_t max_desc; /**< max allowed number of RXDs. */
+ uint16_t min_desc; /**< min allowed number of RXDs. */
+} __rte_cache_aligned;
+
+/**
+ * Ethernet device TX queue information strcuture.
+ * Used to retieve information about configured queue.
+ */
+struct rte_eth_tx_qinfo {
+ struct rte_eth_txconf conf; /**< queue config parameters. */
+ uint16_t nb_desc; /**< configured number of TXDs. */
+ uint16_t max_desc; /**< max allowed number of TXDs. */
+ uint16_t min_desc; /**< min allowed number of TXDs. */
+} __rte_cache_aligned;
+
struct rte_eth_dev;
struct rte_eth_dev_callback;
@@ -1045,6 +1069,12 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
/**< @Check DD bit of specific RX descriptor */
+typedef void (*eth_rx_qinfo_get_t)(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, struct rte_eth_rx_qinfo *qinfo);
+
+typedef void (*eth_tx_qinfo_get_t)(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, struct rte_eth_tx_qinfo *qinfo);
+
typedef int (*mtu_set_t)(struct rte_eth_dev *dev, uint16_t mtu);
/**< @internal Set MTU. */
@@ -1389,8 +1419,13 @@ struct eth_dev_ops {
rss_hash_update_t rss_hash_update;
/** Get current RSS hash configuration. */
rss_hash_conf_get_t rss_hash_conf_get;
- eth_filter_ctrl_t filter_ctrl; /**< common filter control*/
+ eth_filter_ctrl_t filter_ctrl;
+ /**< common filter control. */
eth_set_mc_addr_list_t set_mc_addr_list; /**< set list of mcast addrs */
+ eth_rx_qinfo_get_t rx_qinfo_get;
+ /**< retrieve RX queue information. */
+ eth_tx_qinfo_get_t tx_qinfo_get;
+ /**< retrieve TX queue information. */
};
/**
@@ -3616,6 +3651,46 @@ int rte_eth_remove_rx_callback(uint8_t port_id, uint16_t queue_id,
int rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id,
struct rte_eth_rxtx_callback *user_cb);
+/**
+ * Retrieve information about given port's RX queue.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The RX queue on the Ethernet device for which information
+ * will be retrieved.
+ * @param qinfo
+ * A pointer to a structure of type *rte_eth_rx_qinfo_info* to be filled with
+ * the information of the Ethernet device.
+ *
+ * @return
+ * - 0: Success
+ * - -ENOTSUP: routine is not supported by the device PMD.
+ * - -EINVAL: The port_id or the queue_id is out of range.
+ */
+int rte_eth_rx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_rx_qinfo *qinfo);
+
+/**
+ * Retrieve information about given port's TX queue.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The TX queue on the Ethernet device for which information
+ * will be retrieved.
+ * @param qinfo
+ * A pointer to a structure of type *rte_eth_tx_qinfo_info* to be filled with
+ * the information of the Ethernet device.
+ *
+ * @return
+ * - 0: Success
+ * - -ENOTSUP: routine is not supported by the device PMD.
+ * - -EINVAL: The port_id or the queue_id is out of range.
+ */
+int rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+ struct rte_eth_tx_qinfo *qinfo);
+
#ifdef __cplusplus
}
#endif
--
1.8.5.3
^ permalink raw reply [relevance 3%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 12:14 7% ` Panu Matilainen
@ 2015-06-17 13:21 8% ` Vincent JARDIN
0 siblings, 0 replies; 200+ results
From: Vincent JARDIN @ 2015-06-17 13:21 UTC (permalink / raw)
To: Panu Matilainen, Neil Horman, Thomas Monjalon; +Cc: dev
On 17/06/2015 14:14, Panu Matilainen wrote:
> (initially accidentally sent to announce, resending to dev)
>
> On 06/17/2015 01:35 PM, Neil Horman wrote:
>> On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
>>> Hi all,
>>>
>>> Sometimes there are some important discussions about architecture or
>>> design
>>> which require opinions from several developers. Unfortunately, we cannot
>>> read every threads. Maybe that using the announce mailing list will help
>>> to bring more audience to these discussions.
>>> Please note that
>>> - the announce@ ML is moderated to keep a low traffic,
>>> - every announce email is forwarded to dev@ ML.
>>> In case you want to reply to this email, please use dev@dpdk.org
>>> address.
>>>
>>> There were some debates about software statistics disabling.
>>> Should they be always on or possibly disabled when compiled?
>>> We need to take a decision shortly and discuss (or agree) this proposal:
>>> http://dpdk.org/ml/archives/dev/2015-June/019461.html
>>>
>>> During the development of the release 2.0, there was an agreement to
>>> keep
>>> ABI compatibility or to bring new ABI while keeping old one during
>>> one release.
>>> In case it's not possible to have this transition, the (exceptional)
>>> break
>>> should be acknowledged by several developers.
>>> http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
>>> There were some interesting discussions but not a lot of participants:
>>> http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus=8461
>>>
>>>
>>> During the current development cycle for the release 2.1, the ABI
>>> question
>>> arises many times in different threads.
>>> To add the hash key size field, it is proposed to use a struct
>>> padding gap:
>>> http://dpdk.org/ml/archives/dev/2015-June/019386.html
>>> To support the flow director for VF, there is no proposal yet:
>>> http://dpdk.org/ml/archives/dev/2015-June/019343.html
>>> To add the speed capability, it is proposed to break ABI in the
>>> release 2.2:
>>> http://dpdk.org/ml/archives/dev/2015-June/019225.html
>>> To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
>>> http://dpdk.org/ml/archives/dev/2015-June/019443.html
>>> To add the interrupt mode, it is proposed to add a build-time option
>>> CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking
>>> binary:
>>> http://dpdk.org/ml/archives/dev/2015-June/018947.html
>>> To add the packet type, there is a proposal to add a build-time option
>>> CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
>>> http://dpdk.org/ml/archives/dev/2015-June/019172.html
>>> We must also better document how to remove a deprecated ABI:
>>> http://dpdk.org/ml/archives/dev/2015-June/019465.html
>>> The ABI compatibility is a new constraint and we need to better
>>> understand
>>> what it means and how to proceed. Even the macros are not yet well
>>> documented:
>>> http://dpdk.org/ml/archives/dev/2015-June/019357.html
>>>
>>> Thanks for your attention and your participation in these important
>>> choices.
>>>
>>
>> Thomas-
>> Just to re-iterate what you said earlier, and what was discussed
>> in the
>> previous ABI discussions
>>
>> 1) ABI stability was introduced to promote DPDK's ability to be
>> included with
>> various linux and BSD distributions. Distributions, by and large, favor
>> building libraries as DSO's, favoring security and updatability in
>> favor of all
>> out performance.
>>
>> 2) The desire was to put DPDK developers in a mindset whereby ABI
>> stability was
>> something they needed to think about during development, as the DPDK
>> exposes
>> many data structures and instances that cannot be changed without
>> breaking ABI
>>
>> 3) The versioning mechanism was introduced to allow for backward
>> compatibility
>> during periods in which we needed to support both an old an new ABI
>>
>> 4) As Stephan and others point out, its not expected that we will
>> always be able
>> to maintain ABI, and as such an easy library versioning mechanism was
>> introduced
>> to prevent the loading of an incompatible library with an older
>> application
>>
>> 5) The ABI policy was introduced to create a method by which new ABI
>> facets
>> could be scheduled while allowing distros to prepare their downstream
>> users for
>> the upcomming changes.
>>
>>
>> It seems to me, looking back over these last few months, that we're
>> falling down
>> a bit on our use of (3). I've seen several people take advantage of
>> the ABI
>> scheduled updates, but no one has tried the versioning interface, and
>> as a
>> result patches are getting delayed, which was never my intent. Not
>> sure whats
>> to be done about that, but we should probably address it. Is use of the
>> versionnig interface just too hard or convoluted?
>
> To me it seems that by far the biggest problem with ABI stability in
> DPDK is features requiring changes to public structs (often directly
> allocated and accessed by apps), which is something the symbol
> versioning doesn't directly help with, you'd need to version the structs
> too.
>
> One only needs to glance at the glibc documentation on how to accomplish
> it [1] to see it gets rather involved. Glibc promises backwards
> compatibility for life, so the effort is justified. However in where
> DPDK we're talking about extending compatibility for a few months by
> minimum requirement, people are unlikely to bother.
>
> [1] https://sourceware.org/glibc/wiki/Development/Versioning_A_Structure
Does it means that it requires a specific engineering so we are back to
the needs of using two layers:
a- the direct calls to "non ABI stable layers" (current librte*) for
those we can/are fine to use it,
b- the calls thru such layers that guarantee the ABI stabilities (a
librte_compat?) for those who needs it.
Could both be exposed by the distributions so they can be consumed?
Thank you,
Vincent
^ permalink raw reply [relevance 8%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 10:35 9% ` Neil Horman
2015-06-17 11:06 4% ` Richardson, Bruce
@ 2015-06-17 12:14 7% ` Panu Matilainen
2015-06-17 13:21 8% ` Vincent JARDIN
2015-06-18 8:36 4% ` Zhang, Helin
2 siblings, 1 reply; 200+ results
From: Panu Matilainen @ 2015-06-17 12:14 UTC (permalink / raw)
To: Neil Horman, Thomas Monjalon; +Cc: dev
(initially accidentally sent to announce, resending to dev)
On 06/17/2015 01:35 PM, Neil Horman wrote:
> On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
>> Hi all,
>>
>> Sometimes there are some important discussions about architecture or design
>> which require opinions from several developers. Unfortunately, we cannot
>> read every threads. Maybe that using the announce mailing list will help
>> to bring more audience to these discussions.
>> Please note that
>> - the announce@ ML is moderated to keep a low traffic,
>> - every announce email is forwarded to dev@ ML.
>> In case you want to reply to this email, please use dev@dpdk.org address.
>>
>> There were some debates about software statistics disabling.
>> Should they be always on or possibly disabled when compiled?
>> We need to take a decision shortly and discuss (or agree) this proposal:
>> http://dpdk.org/ml/archives/dev/2015-June/019461.html
>>
>> During the development of the release 2.0, there was an agreement to keep
>> ABI compatibility or to bring new ABI while keeping old one during one release.
>> In case it's not possible to have this transition, the (exceptional) break
>> should be acknowledged by several developers.
>> http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
>> There were some interesting discussions but not a lot of participants:
>> http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus=8461
>>
>> During the current development cycle for the release 2.1, the ABI question
>> arises many times in different threads.
>> To add the hash key size field, it is proposed to use a struct padding gap:
>> http://dpdk.org/ml/archives/dev/2015-June/019386.html
>> To support the flow director for VF, there is no proposal yet:
>> http://dpdk.org/ml/archives/dev/2015-June/019343.html
>> To add the speed capability, it is proposed to break ABI in the release 2.2:
>> http://dpdk.org/ml/archives/dev/2015-June/019225.html
>> To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
>> http://dpdk.org/ml/archives/dev/2015-June/019443.html
>> To add the interrupt mode, it is proposed to add a build-time option
>> CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking binary:
>> http://dpdk.org/ml/archives/dev/2015-June/018947.html
>> To add the packet type, there is a proposal to add a build-time option
>> CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
>> http://dpdk.org/ml/archives/dev/2015-June/019172.html
>> We must also better document how to remove a deprecated ABI:
>> http://dpdk.org/ml/archives/dev/2015-June/019465.html
>> The ABI compatibility is a new constraint and we need to better understand
>> what it means and how to proceed. Even the macros are not yet well documented:
>> http://dpdk.org/ml/archives/dev/2015-June/019357.html
>>
>> Thanks for your attention and your participation in these important choices.
>>
>
> Thomas-
> Just to re-iterate what you said earlier, and what was discussed in the
> previous ABI discussions
>
> 1) ABI stability was introduced to promote DPDK's ability to be included with
> various linux and BSD distributions. Distributions, by and large, favor
> building libraries as DSO's, favoring security and updatability in favor of all
> out performance.
>
> 2) The desire was to put DPDK developers in a mindset whereby ABI stability was
> something they needed to think about during development, as the DPDK exposes
> many data structures and instances that cannot be changed without breaking ABI
>
> 3) The versioning mechanism was introduced to allow for backward compatibility
> during periods in which we needed to support both an old an new ABI
>
> 4) As Stephan and others point out, its not expected that we will always be able
> to maintain ABI, and as such an easy library versioning mechanism was introduced
> to prevent the loading of an incompatible library with an older application
>
> 5) The ABI policy was introduced to create a method by which new ABI facets
> could be scheduled while allowing distros to prepare their downstream users for
> the upcomming changes.
>
>
> It seems to me, looking back over these last few months, that we're falling down
> a bit on our use of (3). I've seen several people take advantage of the ABI
> scheduled updates, but no one has tried the versioning interface, and as a
> result patches are getting delayed, which was never my intent. Not sure whats
> to be done about that, but we should probably address it. Is use of the
> versionnig interface just too hard or convoluted?
To me it seems that by far the biggest problem with ABI stability in
DPDK is features requiring changes to public structs (often directly
allocated and accessed by apps), which is something the symbol
versioning doesn't directly help with, you'd need to version the structs
too.
One only needs to glance at the glibc documentation on how to accomplish
it [1] to see it gets rather involved. Glibc promises backwards
compatibility for life, so the effort is justified. However in where
DPDK we're talking about extending compatibility for a few months by
minimum requirement, people are unlikely to bother.
[1] https://sourceware.org/glibc/wiki/Development/Versioning_A_Structure
- Panu -
^ permalink raw reply [relevance 7%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
@ 2015-06-17 11:17 4% ` Bruce Richardson
2015-06-18 16:32 4% ` Dumitrescu, Cristian
2015-06-18 13:25 8% ` Dumitrescu, Cristian
2 siblings, 1 reply; 200+ results
From: Bruce Richardson @ 2015-06-17 11:17 UTC (permalink / raw)
To: Matthew Hall; +Cc: dev
On Tue, Jun 16, 2015 at 09:36:54PM -0700, Matthew Hall wrote:
> On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> > There were some debates about software statistics disabling.
> > Should they be always on or possibly disabled when compiled?
> > We need to take a decision shortly and discuss (or agree) this proposal:
> > http://dpdk.org/ml/archives/dev/2015-June/019461.html
>
> This goes against the idea I have seen before that we should be moving toward
> a distro-friendly approach where one copy of DPDK can be used by multiple apps
> without having to rebuild it. It seems like it is also a bit ABI hostile
> according to the below goals / discussions.
>
> Jemalloc is also very high-performance code and still manages to allow
> enabling and disabling statistics at runtime. Are we sure it's impossible for
> DPDK or just theorizing?
>
+1 to this. I think that any compile-time option to disable stats should only
be used when we have a proven performance issue with just disabling them at runtime.
I would assume that apps do not switch on or off stats multiple times per second,
so any code branches to track stats or not would be entirely predictable in the
code - since they always go one way. Therefore, when disabledi, we should be looking
at a very minimal overhead per stat. If there are lots of checks for the same
value in the one path, i.e. lots of stats in a hot path, hopefully the compiler
will be smart enough to make the check just once. If not, we can always do
that in the C code by duplicating the hotpath code for with or without stats cases -
again selectable at runtime.
Also, there is also the case where the stats tracking itself is such low overhead
that its not worth disabling. In that case, neither runtime nor compile-time disabling
should need to be provided. For example, any library that is keeping a track of
bursts of packets should not need to have that stat disable option - one increment
or addition per burst of (32) packets is not going to seriously affect any app. :-)
Regards,
/Bruce
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 10:35 9% ` Neil Horman
@ 2015-06-17 11:06 4% ` Richardson, Bruce
2015-06-19 11:08 7% ` Mcnamara, John
2015-06-17 12:14 7% ` Panu Matilainen
2015-06-18 8:36 4% ` Zhang, Helin
2 siblings, 1 reply; 200+ results
From: Richardson, Bruce @ 2015-06-17 11:06 UTC (permalink / raw)
To: Neil Horman, Thomas Monjalon; +Cc: dev
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Neil Horman
> Sent: Wednesday, June 17, 2015 11:35 AM
> To: Thomas Monjalon
> Cc: announce@dpdk.org
> Subject: Re: [dpdk-dev] [dpdk-announce] important design choices -
> statistics - ABI
>
> On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> > Hi all,
> >
> > Sometimes there are some important discussions about architecture or
> > design which require opinions from several developers. Unfortunately,
> > we cannot read every threads. Maybe that using the announce mailing
> > list will help to bring more audience to these discussions.
> > Please note that
> > - the announce@ ML is moderated to keep a low traffic,
> > - every announce email is forwarded to dev@ ML.
> > In case you want to reply to this email, please use dev@dpdk.org
> address.
> >
> > There were some debates about software statistics disabling.
> > Should they be always on or possibly disabled when compiled?
> > We need to take a decision shortly and discuss (or agree) this proposal:
> > http://dpdk.org/ml/archives/dev/2015-June/019461.html
> >
> > During the development of the release 2.0, there was an agreement to
> > keep ABI compatibility or to bring new ABI while keeping old one during
> one release.
> > In case it's not possible to have this transition, the (exceptional)
> > break should be acknowledged by several developers.
> > http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
> > There were some interesting discussions but not a lot of participants:
> >
> > http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus=84
> > 61
> >
> > During the current development cycle for the release 2.1, the ABI
> > question arises many times in different threads.
> > To add the hash key size field, it is proposed to use a struct padding
> gap:
> > http://dpdk.org/ml/archives/dev/2015-June/019386.html
> > To support the flow director for VF, there is no proposal yet:
> > http://dpdk.org/ml/archives/dev/2015-June/019343.html
> > To add the speed capability, it is proposed to break ABI in the release
> 2.2:
> > http://dpdk.org/ml/archives/dev/2015-June/019225.html
> > To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
> > http://dpdk.org/ml/archives/dev/2015-June/019443.html
> > To add the interrupt mode, it is proposed to add a build-time option
> > CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking
> binary:
> > http://dpdk.org/ml/archives/dev/2015-June/018947.html
> > To add the packet type, there is a proposal to add a build-time option
> > CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
> > http://dpdk.org/ml/archives/dev/2015-June/019172.html
> > We must also better document how to remove a deprecated ABI:
> > http://dpdk.org/ml/archives/dev/2015-June/019465.html
> > The ABI compatibility is a new constraint and we need to better
> > understand what it means and how to proceed. Even the macros are not yet
> well documented:
> > http://dpdk.org/ml/archives/dev/2015-June/019357.html
> >
> > Thanks for your attention and your participation in these important
> choices.
> >
>
> Thomas-
> Just to re-iterate what you said earlier, and what was discussed in
> the previous ABI discussions
>
> 1) ABI stability was introduced to promote DPDK's ability to be included
> with various linux and BSD distributions. Distributions, by and large,
> favor building libraries as DSO's, favoring security and updatability in
> favor of all out performance.
>
> 2) The desire was to put DPDK developers in a mindset whereby ABI
> stability was something they needed to think about during development, as
> the DPDK exposes many data structures and instances that cannot be changed
> without breaking ABI
>
> 3) The versioning mechanism was introduced to allow for backward
> compatibility during periods in which we needed to support both an old an
> new ABI
>
> 4) As Stephan and others point out, its not expected that we will always
> be able to maintain ABI, and as such an easy library versioning mechanism
> was introduced to prevent the loading of an incompatible library with an
> older application
>
> 5) The ABI policy was introduced to create a method by which new ABI
> facets could be scheduled while allowing distros to prepare their
> downstream users for the upcomming changes.
>
>
> It seems to me, looking back over these last few months, that we're
> falling down a bit on our use of (3). I've seen several people take
> advantage of the ABI scheduled updates, but no one has tried the
> versioning interface, and as a result patches are getting delayed, which
> was never my intent. Not sure whats to be done about that, but we should
> probably address it. Is use of the versionnig interface just too hard or
> convoluted?
>
> Neil
Hi Neil,
on my end, some suggestions:
1. the documentation on changing an API function provided in rte_compat.h
is really good, but I don't think this is present in our documentation in
the docs folder or on website is it (apologies if it is and I've missed
it)? This needs to go into programmers guide or some other doc (perhaps
the new doc that the coding style went into).
2. The documentation also needs an example of: this is how you add a new
function and update the map file, and this is how you a) mark a function
as deprecated and b) remove it completely. That way we could have one
guide covering API versioning, how to add, modify and remove functions.
3. This doc should also cover how to use the API checker tool, something I
haven't had the chance to look at yet, but should do in the near future!
:-)
Regards,
/Bruce
^ permalink raw reply [relevance 4%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
2015-06-17 9:54 8% ` Morten Brørup
@ 2015-06-17 10:35 9% ` Neil Horman
2015-06-17 11:06 4% ` Richardson, Bruce
` (2 more replies)
2015-06-18 16:55 8% ` O'Driscoll, Tim
3 siblings, 3 replies; 200+ results
From: Neil Horman @ 2015-06-17 10:35 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: announce
On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> Hi all,
>
> Sometimes there are some important discussions about architecture or design
> which require opinions from several developers. Unfortunately, we cannot
> read every threads. Maybe that using the announce mailing list will help
> to bring more audience to these discussions.
> Please note that
> - the announce@ ML is moderated to keep a low traffic,
> - every announce email is forwarded to dev@ ML.
> In case you want to reply to this email, please use dev@dpdk.org address.
>
> There were some debates about software statistics disabling.
> Should they be always on or possibly disabled when compiled?
> We need to take a decision shortly and discuss (or agree) this proposal:
> http://dpdk.org/ml/archives/dev/2015-June/019461.html
>
> During the development of the release 2.0, there was an agreement to keep
> ABI compatibility or to bring new ABI while keeping old one during one release.
> In case it's not possible to have this transition, the (exceptional) break
> should be acknowledged by several developers.
> http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
> There were some interesting discussions but not a lot of participants:
> http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus=8461
>
> During the current development cycle for the release 2.1, the ABI question
> arises many times in different threads.
> To add the hash key size field, it is proposed to use a struct padding gap:
> http://dpdk.org/ml/archives/dev/2015-June/019386.html
> To support the flow director for VF, there is no proposal yet:
> http://dpdk.org/ml/archives/dev/2015-June/019343.html
> To add the speed capability, it is proposed to break ABI in the release 2.2:
> http://dpdk.org/ml/archives/dev/2015-June/019225.html
> To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
> http://dpdk.org/ml/archives/dev/2015-June/019443.html
> To add the interrupt mode, it is proposed to add a build-time option
> CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking binary:
> http://dpdk.org/ml/archives/dev/2015-June/018947.html
> To add the packet type, there is a proposal to add a build-time option
> CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
> http://dpdk.org/ml/archives/dev/2015-June/019172.html
> We must also better document how to remove a deprecated ABI:
> http://dpdk.org/ml/archives/dev/2015-June/019465.html
> The ABI compatibility is a new constraint and we need to better understand
> what it means and how to proceed. Even the macros are not yet well documented:
> http://dpdk.org/ml/archives/dev/2015-June/019357.html
>
> Thanks for your attention and your participation in these important choices.
>
Thomas-
Just to re-iterate what you said earlier, and what was discussed in the
previous ABI discussions
1) ABI stability was introduced to promote DPDK's ability to be included with
various linux and BSD distributions. Distributions, by and large, favor
building libraries as DSO's, favoring security and updatability in favor of all
out performance.
2) The desire was to put DPDK developers in a mindset whereby ABI stability was
something they needed to think about during development, as the DPDK exposes
many data structures and instances that cannot be changed without breaking ABI
3) The versioning mechanism was introduced to allow for backward compatibility
during periods in which we needed to support both an old an new ABI
4) As Stephan and others point out, its not expected that we will always be able
to maintain ABI, and as such an easy library versioning mechanism was introduced
to prevent the loading of an incompatible library with an older application
5) The ABI policy was introduced to create a method by which new ABI facets
could be scheduled while allowing distros to prepare their downstream users for
the upcomming changes.
It seems to me, looking back over these last few months, that we're falling down
a bit on our use of (3). I've seen several people take advantage of the ABI
scheduled updates, but no one has tried the versioning interface, and as a
result patches are getting delayed, which was never my intent. Not sure whats
to be done about that, but we should probably address it. Is use of the
versionnig interface just too hard or convoluted?
Neil
^ permalink raw reply [relevance 9%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
@ 2015-06-17 9:54 8% ` Morten Brørup
2015-06-18 13:00 4% ` Dumitrescu, Cristian
2015-06-17 10:35 9% ` Neil Horman
2015-06-18 16:55 8% ` O'Driscoll, Tim
3 siblings, 1 reply; 200+ results
From: Morten Brørup @ 2015-06-17 9:54 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev
Dear Thomas,
I don't have time to follow the DPDK Developers mailing list, but since you call for feedback, I would like to share my thoughts regarding these design choices.
Regarding the statistics discussion:
1. The suggested solution assumes that, when statistics is disabled, the cost of allocating and maintaining zero-value statistics is negligible. If statistics counters are only available through accessor functions, this is probably true.
However, if statistics counters are directly accessible, e.g. as elements in the fast path data structures of a library, maintaining zero-value statistics may a have memory and/or performance impact.
Since the compile time flag CONFIG_RTE_<LIBRARY_NAME>_STATS_COLLECT already tells the application if the statistics are present or not, the application should simply use this flag to determine if statistics are accessible or not.
2. The suggested solution with only one single flag per library prevents implementing statistics with varying granularity for different purposes. E.g. a library could have one set of statistics counters for ordinary SNMP purposes, and another set of statistics counters for debugging/optimization purposes.
Multiple flags per library should be possible. A hierarchy of flags per library is probably not required.
Regarding the PHY speed ABI:
1. The Ethernet PHY ABI for speed, duplex, etc. should be common throughout the entire DPDK. It might be confusing if some structures/functions use a bitmask to indicate PHY speed/duplex/personality/etc. and other structures/functions use a combination of an unsigned integer, duplex flag, personality enumeration etc. (By personality enumeration, I am referring to PHYs with multiple electrical interfaces. E.g. a dual personality PHY might have both an RJ45 copper interface and an SFP module interface, whereof only one can be active at any time.)
2. The auto-negotiation standard allows the PHY to announce (to its link partner) any subset of its capabilities to its link partner. E.g. a standard 10/100/100 Ethernet PHY (which can handle both 10 and 100 Mbit/s in both half and full duplex and 1 Gbit/s full duplex) can be configured to announce 10 Mbit/s half duplex and 100 Mbit/s full duplex capabilities to its link partner. (Of course, more useful combinations are normally announced, but the purpose of the example is to show that any combination is possible.)
The ABI for auto-negotiation should include options to select the list of capabilities to announce to the link partner. The Linux PHY ABI only allows forcing a selected speed and duplex (thereby disabling auto-negotiation) or enabling auto-negotiation (thereby announcing all possible speeds and duplex combinations the PHY is capable of). Don't make the same mistake in DPDK.
PS: While working for Vitesse Semiconductors (an Ethernet chip company) a long time ago, I actually wrote the API for their line of Ethernet PHYs. So I have hands on experience in this area.
Regarding the discussion about backwards/forwards compatibility in the ABI:
1. Sometimes, ABI breakage is required. That is the cost the users pay for getting the benefits from upgrading to the latest and greatest version of any library. The current solution of requiring acknowledgement from several qualified developers is fine - these developers will consider the cost/benefit on behalf of all the DPDK users and make a qualified decision.
2. It is my general experience that documentation is not always updated to reflect the fine details of the source code, and this also applies to release notes. For open source software, the primary point of documentation is usually the source code itself.
2a. It should be clearly visible directly in the DPDK source code (including makefiles etc.) which ABI (i.e. functions, macros, type definitions etc.) is the current, the deprecated, and the future.
2b. When a developer migrates a project using DPDK from a previous version of the DPDK, it should be easy for the developer to identify all DPDK ABI modifications and variants, e.g. by using a common indicator in the DPDK source code, such as LIBAPIVER, that developer can simply search for.
3. Adding special feature flags, e.g. CONFIG_RTE_EAL_RX_INTR, to indicate a breakage of the ABI, should only be done if it is the intention to keep both the current and the new variants of the feature in the DPDK in the future. Otherwise, such a flag should be combined with the standard ABI version indication, so it is clear that this feature belongs to certain versions (i.e. deprecated, current or future).
Med venlig hilsen / kind regards
Morten Brørup
CTO
SmartShare Systems A/S
Tonsbakken 16-18
DK-2740 Skovlunde
Denmark
Office +45 70 20 00 93
Direct +45 89 93 50 22
Mobile +45 25 40 82 12
mb@smartsharesystems.com
www.smartsharesystems.com
-----Original Message-----
From: announce [mailto:announce-bounces@dpdk.org] On Behalf Of Thomas Monjalon
Sent: 17. juni 2015 01:30
To: announce@dpdk.org
Subject: [dpdk-announce] important design choices - statistics - ABI
Hi all,
Sometimes there are some important discussions about architecture or design which require opinions from several developers. Unfortunately, we cannot read every threads. Maybe that using the announce mailing list will help to bring more audience to these discussions.
Please note that
- the announce@ ML is moderated to keep a low traffic,
- every announce email is forwarded to dev@ ML.
In case you want to reply to this email, please use dev@dpdk.org address.
There were some debates about software statistics disabling.
Should they be always on or possibly disabled when compiled?
We need to take a decision shortly and discuss (or agree) this proposal:
http://dpdk.org/ml/archives/dev/2015-June/019461.html
During the development of the release 2.0, there was an agreement to keep ABI compatibility or to bring new ABI while keeping old one during one release.
In case it's not possible to have this transition, the (exceptional) break should be acknowledged by several developers.
http://dpdk.org/doc/guides-2.0/rel_notes/abi.html
There were some interesting discussions but not a lot of participants:
http://thread.gmane.org/gmane.comp.networking.dpdk.devel/8367/focus=8461
During the current development cycle for the release 2.1, the ABI question arises many times in different threads.
To add the hash key size field, it is proposed to use a struct padding gap:
http://dpdk.org/ml/archives/dev/2015-June/019386.html
To support the flow director for VF, there is no proposal yet:
http://dpdk.org/ml/archives/dev/2015-June/019343.html
To add the speed capability, it is proposed to break ABI in the release 2.2:
http://dpdk.org/ml/archives/dev/2015-June/019225.html
To support vhost-user multiqueues, it is proposed to break ABI in 2.2:
http://dpdk.org/ml/archives/dev/2015-June/019443.html
To add the interrupt mode, it is proposed to add a build-time option CONFIG_RTE_EAL_RX_INTR to switch between compatible and ABI breaking binary:
http://dpdk.org/ml/archives/dev/2015-June/018947.html
To add the packet type, there is a proposal to add a build-time option CONFIG_RTE_NEXT_ABI common to every ABI breaking features:
http://dpdk.org/ml/archives/dev/2015-June/019172.html
We must also better document how to remove a deprecated ABI:
http://dpdk.org/ml/archives/dev/2015-June/019465.html
The ABI compatibility is a new constraint and we need to better understand what it means and how to proceed. Even the macros are not yet well documented:
http://dpdk.org/ml/archives/dev/2015-June/019357.html
Thanks for your attention and your participation in these important choices.
^ permalink raw reply [relevance 8%]
* Re: [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI
@ 2015-06-17 8:23 7% ` Thomas Monjalon
0 siblings, 0 replies; 200+ results
From: Thomas Monjalon @ 2015-06-17 8:23 UTC (permalink / raw)
To: Stephen Hemminger, Matthew Hall; +Cc: dev
2015-06-16 22:28, Stephen Hemminger:
> On Tue, Jun 16, 2015 at 9:36 PM, Matthew Hall <mhall@mhcomputing.net> wrote:
> > On Wed, Jun 17, 2015 at 01:29:47AM +0200, Thomas Monjalon wrote:
> > > There were some debates about software statistics disabling.
> > > Should they be always on or possibly disabled when compiled?
> > > We need to take a decision shortly and discuss (or agree) this proposal:
> > > http://dpdk.org/ml/archives/dev/2015-June/019461.html
> >
> > This goes against the idea I have seen before that we should be moving
> > toward a distro-friendly approach where one copy of DPDK can be used by
> > multiple apps without having to rebuild it. It seems like it is also a
> > bit ABI hostile according to the below goals / discussions.
> >
> > Jemalloc is also very high-performance code and still manages to allow
> > enabling and disabling statistics at runtime. Are we sure it's impossible
> > for DPDK or just theorizing?
Please Matthew, it is better to comment in the thread dedicated to statistics.
[...]
> > Personally to me it seems more important to preserve the ABI on patch
> > releases, like 2.X.Y going to 2.X.Z. But maybe I missed something?
The goal of the ABI deprecation process was to provide a smooth integration
of the release 2.X+1.0. There are 4 months between releases 2.X.0 and 2.X+1.0.
[...]
> > However new-style libraries such as libcurl usually just have init
> > functions which initialize all the secret structs based on some defaults
> > and some user parameters and hide the actual structs from the user.
> > If you want to adjust some you call an adjuster function that modifies
> > the actual secret struct contents, with some enum saying what field to
> > adjust, and the new value you want it to have.
> >
> > If you want to keep a stable ABI for a non-stable library like DPDK,
> > there's a good chance you must begin hiding all these weird device
> > specific structs all over the DPDK from the user needing to directly
> > allocate and modify them.
> > Otherwise the ABI breaks everytime you have to add adjustments,
> > extensions, modifications to all these obscure special features.
>
> The DPDK makes extensive use of inline functions which prevents data hiding
> necessary for ABI stablility. This a fundamental tradeoff, and since the
> whole reason for DPDK is performance; the ABI is going to be a moving target.
>
> It would make more sense to provide a higher level API which was abstracted,
> slower, but stable for applications. But in doing so it would mean giving
> up things like inline lockless rings. Just don't go as far as the Open (not)
> dataplane API;
> which is just an excuse for closed source.
I don't understand what you mean.
^ permalink raw reply [relevance 7%]
Results 13001-13200 of ~18000 next (older) | prev (newer) | reverse | sort options + mbox downloads above
-- links below jump to the message on this page --
2015-05-11 3:46 [dpdk-dev] [PATCH 0/6] extend flow director to support L2_paylod type and VF filtering in i40e driver Jingjing Wu
2015-06-16 3:43 ` [dpdk-dev] [PATCH v2 0/4] extend flow director to support L2_paylod type Jingjing Wu
2015-06-26 2:26 0% ` Xu, HuilongX
2015-06-26 3:14 0% ` Zhang, Helin
2015-05-26 15:41 [dpdk-dev] [PATCH v4 0/4] bonding corrections and additions Eric Kinzie
2015-05-26 15:41 ` [dpdk-dev] [PATCH v4 3/4] bond mode 4: allow external state machine Eric Kinzie
2015-07-02 13:30 4% ` Declan Doherty
2015-05-30 0:37 [dpdk-dev] [PATCH 0/2] User-space Ethtool Liang-Min Larry Wang
2015-06-17 22:22 ` [dpdk-dev] [PATCH v7 0/4] " Liang-Min Larry Wang
2015-06-18 2:04 3% ` Stephen Hemminger
2015-06-18 12:47 0% ` Wang, Liang-min
2015-06-23 15:19 0% ` Wang, Liang-min
2015-06-01 7:33 [dpdk-dev] [PATCH v6 00/18] unified packet type Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 02/18] ixgbe: support unified packet type in vectorized PMD Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 03/18] mbuf: add definitions of unified packet types Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 04/18] e1000: replace bit mask based packet type with unified packet type Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 05/18] ixgbe: " Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 06/18] i40e: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 07/18] enic: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 08/18] vmxnet3: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 09/18] fm10k: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 10/18] app/test-pipeline: " Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 11/18] app/testpmd: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 12/18] app/test: Remove useless code Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 14/18] examples/ip_reassembly: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 15/18] examples/l3fwd-acl: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 16/18] examples/l3fwd-power: " Helin Zhang
2015-06-19 8:14 3% ` [dpdk-dev] [PATCH v7 17/18] examples/l3fwd: " Helin Zhang
2015-06-19 8:14 4% ` [dpdk-dev] [PATCH v7 18/18] mbuf: remove old packet type bit masks Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 01/18] mbuf: redefine packet_type in rte_mbuf Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 02/18] ixgbe: support unified packet type in vectorized PMD Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 03/18] mbuf: add definitions of unified packet types Helin Zhang
2015-06-30 8:43 0% ` Olivier MATZ
2015-07-02 1:30 0% ` Zhang, Helin
2015-07-02 9:31 0% ` Olivier MATZ
2015-07-03 1:30 0% ` Zhang, Helin
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 04/18] e1000: replace bit mask based packet type with unified packet type Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 05/18] ixgbe: " Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 06/18] i40e: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 07/18] enic: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 08/18] vmxnet3: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 09/18] fm10k: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 10/18] app/test-pipeline: " Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 11/18] app/testpmd: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 12/18] app/test: Remove useless code Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 13/18] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 14/18] examples/ip_reassembly: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 15/18] examples/l3fwd-acl: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 16/18] examples/l3fwd-power: " Helin Zhang
2015-06-23 1:50 3% ` [dpdk-dev] [PATCH v8 17/18] examples/l3fwd: " Helin Zhang
2015-06-23 1:50 4% ` [dpdk-dev] [PATCH v8 18/18] mbuf: remove old packet type bit masks Helin Zhang
2015-06-23 16:13 0% ` [dpdk-dev] [PATCH v8 00/18] unified packet type Ananyev, Konstantin
2015-07-02 8:45 0% ` Liu, Yong
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 00/19] " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 01/19] mbuf: redefine packet_type in rte_mbuf Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 02/19] mbuf: add definitions of unified packet types Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 03/19] e1000: replace bit mask based packet type with unified packet type Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 04/19] ixgbe: " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 05/19] i40e: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 06/19] enic: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 07/19] vmxnet3: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 08/19] fm10k: " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 09/19] cxgbe: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 10/19] app/test-pipeline: " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 11/19] app/testpmd: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 12/19] app/test: Remove useless code Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 13/19] examples/ip_fragmentation: replace bit mask based packet type with unified packet type Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 14/19] examples/ip_reassembly: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 15/19] examples/l3fwd-acl: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 16/19] examples/l3fwd-power: " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 17/19] examples/l3fwd: " Helin Zhang
2015-07-03 8:32 3% ` [dpdk-dev] [PATCH v9 18/19] examples/tep_termination: " Helin Zhang
2015-07-03 8:32 4% ` [dpdk-dev] [PATCH v9 19/19] mbuf: remove old packet type bit masks Helin Zhang
2015-06-02 3:16 [dpdk-dev] [PATCH v2 0/6] support i40e QinQ stripping and insertion Helin Zhang
2015-06-11 7:03 ` [dpdk-dev] [PATCH v3 0/7] " Helin Zhang
2015-06-11 7:03 ` [dpdk-dev] [PATCH v3 2/7] mbuf: use the reserved 16 bits for double vlan Helin Zhang
2015-06-25 8:31 3% ` Zhang, Helin
2015-06-28 20:36 0% ` Thomas Monjalon
2015-06-30 7:33 3% ` Olivier MATZ
2015-06-05 8:16 [dpdk-dev] [PATCH v3 0/4] enable mirror functionality in i40e driver Jingjing Wu
2015-06-10 6:24 ` [dpdk-dev] [PATCH v4 " Jingjing Wu
2015-06-10 6:24 ` [dpdk-dev] [PATCH v4 1/4] ethdev: rename rte_eth_vmdq_mirror_conf Jingjing Wu
2015-06-26 7:03 5% ` Wu, Jingjing
2015-07-06 1:27 0% ` Wu, Jingjing
2015-06-05 14:33 [dpdk-dev] [PATCH 0/6] Cuckoo hash Pablo de Lara
2015-06-05 14:33 ` [dpdk-dev] [PATCH 2/6] hash: replace existing hash library with cuckoo hash implementation Pablo de Lara
2015-06-18 9:50 4% ` Bruce Richardson
2015-06-25 22:05 4% ` [dpdk-dev] [PATCH v2 00/11] Cuckoo hash Pablo de Lara
2015-06-25 22:05 ` [dpdk-dev] [PATCH v2 08/11] hash: add new functionality to store data in hash table Pablo de Lara
2015-06-26 16:49 ` Stephen Hemminger
2015-06-28 22:23 ` De Lara Guarch, Pablo
2015-06-30 7:36 3% ` Stephen Hemminger
2015-06-25 22:05 14% ` [dpdk-dev] [PATCH v2 10/11] doc: announce ABI change of librte_hash Pablo de Lara
2015-06-28 22:25 4% ` [dpdk-dev] [PATCH v3 00/11] Cuckoo hash Pablo de Lara
2015-06-28 22:25 14% ` [dpdk-dev] [PATCH v3 10/11] doc: announce ABI change of librte_hash Pablo de Lara
2015-06-05 14:55 [dpdk-dev] [PATCH] lib: fix RTE_MBUF_METADATA macros Daniel Mrzyglod
2015-06-05 15:31 ` Dumitrescu, Cristian
2015-06-22 20:16 0% ` Thomas Monjalon
2015-06-22 20:23 0% ` Cyril Chemparathy
2015-06-22 20:34 0% ` Cyril Chemparathy
2015-06-06 10:32 [dpdk-dev] [PATCH v2 0/7] dynamic memzone Sergio Gonzalez Monroy
2015-06-19 17:21 4% ` [dpdk-dev] [PATCH v3 0/9] Dynamic memzone Sergio Gonzalez Monroy
2015-06-19 17:21 1% ` [dpdk-dev] [PATCH v3 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-19 17:21 14% ` [dpdk-dev] [PATCH v3 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-25 14:05 4% ` [dpdk-dev] [PATCH v4 0/9] Dynamic memzone Sergio Gonzalez Monroy
2015-06-25 14:05 1% ` [dpdk-dev] [PATCH v4 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-25 14:05 14% ` [dpdk-dev] [PATCH v4 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-26 11:32 4% ` [dpdk-dev] [PATCH v5 0/9] Dynamic memzones Sergio Gonzalez Monroy
2015-06-26 11:32 1% ` [dpdk-dev] [PATCH v5 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-26 11:32 14% ` [dpdk-dev] [PATCH v5 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-26 15:29 4% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Sergio Gonzalez Monroy
2015-06-26 15:29 1% ` [dpdk-dev] [PATCH v6 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-06-26 15:29 14% ` [dpdk-dev] [PATCH v6 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-26 16:13 0% ` [dpdk-dev] [PATCH v6 0/9] Dynamic memzones Ananyev, Konstantin
2015-07-03 9:55 4% ` [dpdk-dev] [PATCH v7 " Sergio Gonzalez Monroy
2015-07-03 9:55 1% ` [dpdk-dev] [PATCH v7 2/9] eal: memzone allocated by malloc Sergio Gonzalez Monroy
2015-07-03 9:55 14% ` [dpdk-dev] [PATCH v7 8/9] doc: announce ABI change of librte_malloc Sergio Gonzalez Monroy
2015-06-08 5:28 [dpdk-dev] [PATCH v12 00/14] Interrupt mode PMD Cunming Liang
2015-06-19 4:00 4% ` [dpdk-dev] [PATCH v13 " Cunming Liang
2015-06-19 4:00 2% ` [dpdk-dev] [PATCH v13 10/14] ethdev: add rx intr enable, disable and ctl functions Cunming Liang
2015-06-19 4:00 10% ` [dpdk-dev] [PATCH v13 14/14] abi: fix v2.1 abi broken issue Cunming Liang
2015-06-10 5:52 [dpdk-dev] [PATCH v2 0/7] Support multiple queues in vhost Ouyang Changchun
2015-06-15 7:56 ` [dpdk-dev] [PATCH v3 0/9] " Ouyang Changchun
2015-06-15 7:56 ` [dpdk-dev] [PATCH v3 2/9] lib_vhost: Support multiple queues in virtio dev Ouyang Changchun
2015-06-18 13:34 3% ` Flavio Leitner
2015-06-19 1:17 3% ` Ouyang, Changchun
2015-06-12 11:28 [dpdk-dev] [PATCH 0/4] ethdev: Add checks for function support in driver Bruce Richardson
2015-06-12 17:32 ` [dpdk-dev] [PATCH 4/4] ethdev: check support for rx_queue_count and descriptor_done fns Roger B. Melton
2015-06-15 10:14 ` Bruce Richardson
2015-07-06 15:11 3% ` Thomas Monjalon
2015-06-16 23:29 [dpdk-dev] [dpdk-announce] important design choices - statistics - ABI Thomas Monjalon
2015-06-17 4:36 ` Matthew Hall
2015-06-17 5:28 ` Stephen Hemminger
2015-06-17 8:23 7% ` Thomas Monjalon
2015-06-17 11:17 4% ` Bruce Richardson
2015-06-18 16:32 4% ` Dumitrescu, Cristian
2015-06-18 13:25 8% ` Dumitrescu, Cristian
2015-06-17 9:54 8% ` Morten Brørup
2015-06-18 13:00 4% ` Dumitrescu, Cristian
2015-06-17 10:35 9% ` Neil Horman
2015-06-17 11:06 4% ` Richardson, Bruce
2015-06-19 11:08 7% ` Mcnamara, John
2015-06-17 12:14 7% ` Panu Matilainen
2015-06-17 13:21 8% ` Vincent JARDIN
2015-06-18 8:36 4% ` Zhang, Helin
2015-06-18 16:55 8% ` O'Driscoll, Tim
2015-06-18 21:13 4% ` Vincent JARDIN
2015-06-19 10:26 9% ` Neil Horman
2015-06-19 12:32 9% ` Thomas Monjalon
2015-06-19 13:02 9% ` Neil Horman
2015-06-19 13:16 4% ` Thomas Monjalon
2015-06-19 15:27 9% ` Neil Horman
2015-06-19 15:51 9% ` Thomas Monjalon
2015-06-19 16:13 9% ` Thomas F Herbert
2015-06-19 17:02 8% ` Thomas Monjalon
2015-06-19 17:57 9% ` Thomas F Herbert
2015-06-17 5:48 [dpdk-dev] [PATCH] doc: announce ABI changes planned for unified packet type Helin Zhang
2015-07-03 8:49 21% ` [dpdk-dev] [PATCH v2] " Helin Zhang
2015-06-17 14:06 [dpdk-dev] rte_mbuf.next in 2nd cacheline Bruce Richardson
[not found] ` <0DE313B5-C9F0-4879-9D92-838ED088202C@cisco.com>
[not found] ` <27EA8870B328F74E88180827A0F816396BD43720@xmb-aln-x10.cisco.com>
[not found] ` <59AF69C657FD0841A61C55336867B5B0345592CD@IRSMSX103.ger.corp.intel.com>
[not found] ` <1FD9B82B8BF2CF418D9A1000154491D97450B186@ORSMSX102.amr.corp.intel.com>
[not found] ` <27EA8870B328F74E88180827A0F816396BD43891@xmb-aln-x10.cisco.com>
[not found] ` <2601191342CEEE43887BDE71AB97725836A1237C@irsmsx105.ger.corp.intel.com>
2015-06-17 18:50 3% ` Ananyev, Konstantin
2015-06-17 16:54 [dpdk-dev] [PATCH 0/5] ethdev: add new API to retrieve RX/TX queue information Konstantin Ananyev
2015-06-17 16:54 3% ` [dpdk-dev] [PATCH 1/5] " Konstantin Ananyev
2015-06-18 13:18 ` [dpdk-dev] [PATCHv2 0/5] " Konstantin Ananyev
2015-06-18 13:18 2% ` [dpdk-dev] [PATCHv2 1/5] " Konstantin Ananyev
2015-06-18 13:30 ` [dpdk-dev] [PATCHv2 0/5] " Walukiewicz, Miroslaw
2015-06-18 14:17 3% ` Ananyev, Konstantin
2015-06-18 14:37 0% ` Walukiewicz, Miroslaw
2015-06-18 13:58 3% ` Bruce Richardson
2015-06-18 14:43 5% [dpdk-dev] [PATCH v2 1/2] Added ETH_SPEED_CAP bitmap in rte_eth_dev_info Morten Brørup
2015-06-18 15:06 0% ` Marc Sune
2015-06-18 15:33 3% ` Thomas Monjalon
2015-06-19 3:37 [dpdk-dev] clang build failing in v2.0.0 from poisoned symbols Matthew Hall
2015-06-19 4:31 ` Matthew Hall
2015-06-19 10:15 ` Bruce Richardson
2015-06-21 2:37 ` [dpdk-dev] DPDK v2.0.0 has different rte_eal_pci_probe() behavior Matthew Hall
[not found] ` <CAO1kT8_C2QJUrNk-fqOQd=WmOkpvNw5jCvxEhfPdHwyCwBuyKA@mail.gmail.com>
2015-06-22 0:32 4% ` Matthew Hall
2015-06-19 9:41 [dpdk-dev] [PATCH v5 00/13] port: added port statistics Maciej Gajdzica
2015-06-19 9:41 ` [dpdk-dev] [PATCH v5 01/13] port: added structures for port stats and config option Maciej Gajdzica
2015-06-23 13:55 3% ` Thomas Monjalon
2015-06-23 14:30 3% ` Dumitrescu, Cristian
2015-06-23 14:54 0% ` Thomas Monjalon
2015-06-23 15:21 0% ` Dumitrescu, Cristian
2015-06-23 15:16 3% ` Neil Horman
[not found] <1434999524-26528-1-git-send-email-cchemparathy@ezchip.com>
2015-06-22 18:58 ` [dpdk-dev] [PATCH v2 08/12] mempool: allow config override on element alignment Cyril Chemparathy
2015-06-23 0:31 3% ` Ananyev, Konstantin
2015-06-23 20:43 4% ` Cyril Chemparathy
2015-06-23 21:21 0% ` Ananyev, Konstantin
2015-06-23 19:33 [dpdk-dev] [PATCH 1/2] rte_compat.h : Clean up some typos Neil Horman
2015-06-23 19:33 14% ` [dpdk-dev] [PATCH 2/2] ABI: Add some documentation Neil Horman
2015-06-24 11:21 4% ` Mcnamara, John
2015-06-24 18:34 ` [dpdk-dev] [PATCHv2 1/2] rte_compat.h : Clean up some typos Neil Horman
2015-06-24 18:34 14% ` [dpdk-dev] [PATCHv2 2/2] ABI: Add some documentation Neil Horman
2015-06-24 21:09 9% ` Thomas Monjalon
2015-06-25 11:35 9% ` Neil Horman
2015-06-25 13:22 7% ` Thomas Monjalon
2015-06-25 7:19 4% ` Zhang, Helin
2015-06-25 7:42 4% ` Gonzalez Monroy, Sergio
2015-06-25 8:00 4% ` Gonzalez Monroy, Sergio
2015-06-25 12:25 4% ` Neil Horman
2015-06-25 14:35 ` [dpdk-dev] [PATCHv3 1/3] rte_compat.h : Clean up some typos Neil Horman
2015-06-25 14:35 ` [dpdk-dev] [PATCHv3 2/3] rte_compat: Add MAP_STATIC_SYMBOL macro Neil Horman
2015-06-26 12:52 ` Thomas Monjalon
2015-06-26 14:30 3% ` Neil Horman
2015-06-28 20:13 0% ` Thomas Monjalon
2015-06-29 13:44 0% ` Neil Horman
2015-06-25 14:35 28% ` [dpdk-dev] [PATCHv3 3/3] ABI: Add some documentation Neil Horman
2015-06-26 13:00 4% ` Thomas Monjalon
2015-06-26 14:54 4% ` Neil Horman
2015-06-28 20:24 8% ` Thomas Monjalon
2015-06-29 13:53 4% ` Neil Horman
2015-06-29 13:59 ` [dpdk-dev] [PATCHv4 1/4] rte_compat.h : Clean up some typos Neil Horman
2015-06-29 13:59 28% ` [dpdk-dev] [PATCHv4 4/4] ABI: Add some documentation Neil Horman
2015-06-29 15:07 7% ` Thomas Monjalon
2015-06-26 12:59 3% [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps Maryam Tahhan
2015-06-26 12:59 9% ` [dpdk-dev] [PATCH v3 4/7] ethdev: remove HW specific stats in stats structs Maryam Tahhan
2015-06-26 14:03 0% ` Kyle Larose
2015-06-26 14:30 11% ` Tahhan, Maryam
2015-06-26 14:37 0% ` Kyle Larose
2015-07-01 14:27 0% ` [dpdk-dev] [PATCH v3 0/7] Expose IXGBE extended stats to DPDK apps Tahhan, Maryam
2015-06-29 13:42 4% [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping John McNamara
2015-06-29 13:42 14% ` [dpdk-dev] [PATCH v2 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
2015-07-02 1:24 0% ` [dpdk-dev] [PATCH v2 0/7] ethdev: add support for ieee1588 timestamping Lu, Wenzhuo
2015-07-02 15:16 4% ` [dpdk-dev] [PATCH v3 " John McNamara
2015-07-02 15:16 14% ` [dpdk-dev] [PATCH v3 7/7] abi: announce mbuf addition for ieee1588 in DPDK 2.2 John McNamara
2015-07-06 13:16 4% ` Thomas Monjalon
2015-07-03 8:22 0% ` [dpdk-dev] [PATCH v3 0/7] ethdev: add support for ieee1588 timestamping Lu, Wenzhuo
2015-07-01 6:18 3% [dpdk-dev] rte_lpm4 with expanded next hop support now available Matthew Hall
2015-07-01 11:20 4% ` Bruce Richardson
2015-07-01 15:59 0% ` Matthew Hall
2015-07-02 11:52 9% [dpdk-dev] [PATCH] doc: fix minor sphinx build warning John McNamara
2015-07-02 12:18 3% ` Thomas Monjalon
2015-07-02 13:28 0% ` Mcnamara, John
2015-07-02 13:50 [dpdk-dev] [PATCH 0/3] doc: added guidelines on dpdk documentation John McNamara
2015-07-02 13:50 3% ` [dpdk-dev] [PATCH 2/3] " John McNamara
2015-07-02 16:20 0% ` Thomas Monjalon
2015-07-02 14:15 8% [dpdk-dev] [PATCH v2] doc: fix minor sphinx build warning John McNamara
2015-07-06 14:55 0% ` Thomas Monjalon
2015-07-02 22:05 20% [dpdk-dev] [PATCH] mk: enable next abi in static libs Thomas Monjalon
2015-07-06 13:18 4% ` Thomas Monjalon
2015-07-06 13:35 9% ` Neil Horman
2015-07-06 13:49 8% ` Thomas Monjalon
2015-07-06 18:22 9% ` Neil Horman
2015-07-06 21:44 9% ` Thomas Monjalon
2015-07-05 17:39 3% [dpdk-dev] [PATCH v4 0/8] Expose IXGBE extended stats to DPDK apps Maryam Tahhan
2015-07-05 17:39 9% ` [dpdk-dev] [PATCH v4 4/8] ethdev: remove HW specific stats in stats structs Maryam Tahhan
2015-07-06 13:28 [dpdk-dev] [PATCH 0/2] Native uio-based PMD for Mellanox ConnectX-3 devices leeopop
2015-07-06 13:28 ` [dpdk-dev] [PATCH 1/2] eal/persistent: new library to hold memory region after program exit leeopop
2015-07-06 19:19 1% ` Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).