get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/8065/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 8065,
    "url": "https://patches.dpdk.org/api/patches/8065/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1445942009-10898-1-git-send-email-medvedkinv@gmail.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1445942009-10898-1-git-send-email-medvedkinv@gmail.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1445942009-10898-1-git-send-email-medvedkinv@gmail.com",
    "date": "2015-10-27T10:33:29",
    "name": "[dpdk-dev,v1,0/3] lpm: increase number of next hops for lpm (ipv4)",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": true,
    "hash": "41bbb20b213f5451c7e440ce9743ac81090b5220",
    "submitter": {
        "id": 210,
        "url": "https://patches.dpdk.org/api/people/210/?format=api",
        "name": "Vladimir Medvedkin",
        "email": "medvedkinv@gmail.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1445942009-10898-1-git-send-email-medvedkinv@gmail.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/8065/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/8065/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 1B03C567C;\n\tTue, 27 Oct 2015 11:36:57 +0100 (CET)",
            "from mailrelay1.rambler.ru (mailrelay1.rambler.ru [81.19.66.239])\n\tby dpdk.org (Postfix) with ESMTP id 6B6F0378E\n\tfor <dev@dpdk.org>; Tue, 27 Oct 2015 11:36:56 +0100 (CET)",
            "from hst119.rambler.ru (unknown [10.201.1.2])\n\tby mailrelay1.rambler.ru (Postfix) with ESMTP id 3nlTx36LM0zK2f;\n\tTue, 27 Oct 2015 13:36:55 +0300 (MSK)"
        ],
        "From": "Vladimir Medvedkin <medvedkinv@gmail.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 27 Oct 2015 06:33:29 -0400",
        "Message-Id": "<1445942009-10898-1-git-send-email-medvedkinv@gmail.com>",
        "X-Mailer": "git-send-email 1.8.3.2",
        "In-Reply-To": "<CANDrEH=hODQXTG+52HjUJ3vLxVHGg3evRqcTnmNWp4+BUVfrHg@mail.gmail.com>",
        "References": "<CANDrEH=hODQXTG+52HjUJ3vLxVHGg3evRqcTnmNWp4+BUVfrHg@mail.gmail.com>",
        "X-Rcpt-To": "<medvedkinv@gmail.com>, <dev@dpdk.org>",
        "Subject": "[dpdk-dev] [PATCH v1 0/3] lpm: increase number of next hops for lpm\n\t(ipv4)",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>\n---\n config/common_bsdapp     |   1 +\n config/common_linuxapp   |   1 +\n lib/librte_lpm/rte_lpm.c | 194 +++++++++++++++++++++++++++++------------------\n lib/librte_lpm/rte_lpm.h | 163 +++++++++++++++++++++++----------------\n 4 files changed, 219 insertions(+), 140 deletions(-)",
    "diff": "diff --git a/config/common_bsdapp b/config/common_bsdapp\nindex b37dcf4..408cc2c 100644\n--- a/config/common_bsdapp\n+++ b/config/common_bsdapp\n@@ -344,6 +344,7 @@ CONFIG_RTE_LIBRTE_JOBSTATS=y\n #\n CONFIG_RTE_LIBRTE_LPM=y\n CONFIG_RTE_LIBRTE_LPM_DEBUG=n\n+CONFIG_RTE_LIBRTE_LPM_ASNUM=n\n \n #\n # Compile librte_acl\ndiff --git a/config/common_linuxapp b/config/common_linuxapp\nindex 0de43d5..1c60e63 100644\n--- a/config/common_linuxapp\n+++ b/config/common_linuxapp\n@@ -352,6 +352,7 @@ CONFIG_RTE_LIBRTE_JOBSTATS=y\n #\n CONFIG_RTE_LIBRTE_LPM=y\n CONFIG_RTE_LIBRTE_LPM_DEBUG=n\n+CONFIG_RTE_LIBRTE_LPM_ASNUM=n\n \n #\n # Compile librte_acl\ndiff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c\nindex 163ba3c..363b400 100644\n--- a/lib/librte_lpm/rte_lpm.c\n+++ b/lib/librte_lpm/rte_lpm.c\n@@ -159,9 +159,11 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,\n \n \tlpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list);\n \n-\tRTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl24_entry) != 2);\n-\tRTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl8_entry) != 2);\n-\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tRTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl_entry) != 8);\n+#else\n+\tRTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl_entry) != 4);\n+#endif\n \t/* Check user arguments. */\n \tif ((name == NULL) || (socket_id < -1) || (max_rules == 0)){\n \t\trte_errno = EINVAL;\n@@ -261,7 +263,7 @@ rte_lpm_free(struct rte_lpm *lpm)\n  */\n static inline int32_t\n rule_add(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n-\tuint8_t next_hop)\n+\tstruct rte_lpm_res *res)\n {\n \tuint32_t rule_gindex, rule_index, last_rule;\n \tint i;\n@@ -282,8 +284,11 @@ rule_add(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \n \t\t\t/* If rule already exists update its next_hop and return. */\n \t\t\tif (lpm->rules_tbl[rule_index].ip == ip_masked) {\n-\t\t\t\tlpm->rules_tbl[rule_index].next_hop = next_hop;\n-\n+\t\t\t\tlpm->rules_tbl[rule_index].next_hop = res->next_hop;\n+\t\t\t\tlpm->rules_tbl[rule_index].fwd_class = res->fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t\tlpm->rules_tbl[rule_index].as_num = res->as_num;\n+#endif\n \t\t\t\treturn rule_index;\n \t\t\t}\n \t\t}\n@@ -320,7 +325,11 @@ rule_add(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \n \t/* Add the new rule. */\n \tlpm->rules_tbl[rule_index].ip = ip_masked;\n-\tlpm->rules_tbl[rule_index].next_hop = next_hop;\n+\tlpm->rules_tbl[rule_index].next_hop = res->next_hop;\n+\tlpm->rules_tbl[rule_index].fwd_class = res->fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tlpm->rules_tbl[rule_index].as_num = res->as_num;\n+#endif\n \n \t/* Increment the used rules counter for this rule group. */\n \tlpm->rule_info[depth - 1].used_rules++;\n@@ -382,10 +391,10 @@ rule_find(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth)\n  * Find, clean and allocate a tbl8.\n  */\n static inline int32_t\n-tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8)\n+tbl8_alloc(struct rte_lpm_tbl_entry *tbl8)\n {\n \tuint32_t tbl8_gindex; /* tbl8 group index. */\n-\tstruct rte_lpm_tbl8_entry *tbl8_entry;\n+\tstruct rte_lpm_tbl_entry *tbl8_entry;\n \n \t/* Scan through tbl8 to find a free (i.e. INVALID) tbl8 group. */\n \tfor (tbl8_gindex = 0; tbl8_gindex < RTE_LPM_TBL8_NUM_GROUPS;\n@@ -393,12 +402,12 @@ tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8)\n \t\ttbl8_entry = &tbl8[tbl8_gindex *\n \t\t                   RTE_LPM_TBL8_GROUP_NUM_ENTRIES];\n \t\t/* If a free tbl8 group is found clean it and set as VALID. */\n-\t\tif (!tbl8_entry->valid_group) {\n+\t\tif (!tbl8_entry->ext_valid) {\n \t\t\tmemset(&tbl8_entry[0], 0,\n \t\t\t\t\tRTE_LPM_TBL8_GROUP_NUM_ENTRIES *\n \t\t\t\t\tsizeof(tbl8_entry[0]));\n \n-\t\t\ttbl8_entry->valid_group = VALID;\n+\t\t\ttbl8_entry->ext_valid = VALID;\n \n \t\t\t/* Return group index for allocated tbl8 group. */\n \t\t\treturn tbl8_gindex;\n@@ -410,46 +419,50 @@ tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8)\n }\n \n static inline void\n-tbl8_free(struct rte_lpm_tbl8_entry *tbl8, uint32_t tbl8_group_start)\n+tbl8_free(struct rte_lpm_tbl_entry *tbl8, uint32_t tbl8_group_start)\n {\n \t/* Set tbl8 group invalid*/\n-\ttbl8[tbl8_group_start].valid_group = INVALID;\n+\ttbl8[tbl8_group_start].ext_valid = INVALID;\n }\n \n static inline int32_t\n add_depth_small(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n-\t\tuint8_t next_hop)\n+\t\tstruct rte_lpm_res *res)\n {\n \tuint32_t tbl24_index, tbl24_range, tbl8_index, tbl8_group_end, i, j;\n \n \t/* Calculate the index into Table24. */\n \ttbl24_index = ip >> 8;\n \ttbl24_range = depth_to_range(depth);\n+\tstruct rte_lpm_tbl_entry new_tbl_entry = {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t.as_num\t= res->as_num,\n+#endif\n+\t\t.next_hop = res->next_hop,\n+\t\t.fwd_class  = res->fwd_class,\n+\t\t.ext_valid = 0,\n+\t\t.depth = depth,\n+\t\t.valid = VALID,\n+\t};\n+\n \n \tfor (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) {\n \t\t/*\n \t\t * For invalid OR valid and non-extended tbl 24 entries set\n \t\t * entry.\n \t\t */\n-\t\tif (!lpm->tbl24[i].valid || (lpm->tbl24[i].ext_entry == 0 &&\n+\t\tif (!lpm->tbl24[i].valid || (lpm->tbl24[i].ext_valid == 0 &&\n \t\t\t\tlpm->tbl24[i].depth <= depth)) {\n \n-\t\t\tstruct rte_lpm_tbl24_entry new_tbl24_entry = {\n-\t\t\t\t{ .next_hop = next_hop, },\n-\t\t\t\t.valid = VALID,\n-\t\t\t\t.ext_entry = 0,\n-\t\t\t\t.depth = depth,\n-\t\t\t};\n-\n \t\t\t/* Setting tbl24 entry in one go to avoid race\n \t\t\t * conditions\n \t\t\t */\n-\t\t\tlpm->tbl24[i] = new_tbl24_entry;\n+\t\t\tlpm->tbl24[i] = new_tbl_entry;\n \n \t\t\tcontinue;\n \t\t}\n \n-\t\tif (lpm->tbl24[i].ext_entry == 1) {\n+\t\tif (lpm->tbl24[i].ext_valid == 1) {\n \t\t\t/* If tbl24 entry is valid and extended calculate the\n \t\t\t *  index into tbl8.\n \t\t\t */\n@@ -461,19 +474,14 @@ add_depth_small(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n \t\t\tfor (j = tbl8_index; j < tbl8_group_end; j++) {\n \t\t\t\tif (!lpm->tbl8[j].valid ||\n \t\t\t\t\t\tlpm->tbl8[j].depth <= depth) {\n-\t\t\t\t\tstruct rte_lpm_tbl8_entry\n-\t\t\t\t\t\tnew_tbl8_entry = {\n-\t\t\t\t\t\t.valid = VALID,\n-\t\t\t\t\t\t.valid_group = VALID,\n-\t\t\t\t\t\t.depth = depth,\n-\t\t\t\t\t\t.next_hop = next_hop,\n-\t\t\t\t\t};\n+\n+\t\t\t\t\tnew_tbl_entry.ext_valid = VALID;\n \n \t\t\t\t\t/*\n \t\t\t\t\t * Setting tbl8 entry in one go to avoid\n \t\t\t\t\t * race conditions\n \t\t\t\t\t */\n-\t\t\t\t\tlpm->tbl8[j] = new_tbl8_entry;\n+\t\t\t\t\tlpm->tbl8[j] = new_tbl_entry;\n \n \t\t\t\t\tcontinue;\n \t\t\t\t}\n@@ -486,7 +494,7 @@ add_depth_small(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n \n static inline int32_t\n add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n-\t\tuint8_t next_hop)\n+\t\tstruct rte_lpm_res *res)\n {\n \tuint32_t tbl24_index;\n \tint32_t tbl8_group_index, tbl8_group_start, tbl8_group_end, tbl8_index,\n@@ -512,7 +520,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \t\t/* Set tbl8 entry. */\n \t\tfor (i = tbl8_index; i < (tbl8_index + tbl8_range); i++) {\n \t\t\tlpm->tbl8[i].depth = depth;\n-\t\t\tlpm->tbl8[i].next_hop = next_hop;\n+\t\t\tlpm->tbl8[i].next_hop = res->next_hop;\n+\t\t\tlpm->tbl8[i].fwd_class = res->fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\tlpm->tbl8[i].as_num = res->as_num;\n+#endif\n \t\t\tlpm->tbl8[i].valid = VALID;\n \t\t}\n \n@@ -522,17 +534,17 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \t\t * so assign whole structure in one go\n \t\t */\n \n-\t\tstruct rte_lpm_tbl24_entry new_tbl24_entry = {\n-\t\t\t{ .tbl8_gindex = (uint8_t)tbl8_group_index, },\n-\t\t\t.valid = VALID,\n-\t\t\t.ext_entry = 1,\n+\t\tstruct rte_lpm_tbl_entry new_tbl24_entry = {\n+\t\t\t.tbl8_gindex = (uint16_t)tbl8_group_index,\n \t\t\t.depth = 0,\n+\t\t\t.ext_valid = 1,\n+\t\t\t.valid = VALID,\n \t\t};\n \n \t\tlpm->tbl24[tbl24_index] = new_tbl24_entry;\n \n \t}/* If valid entry but not extended calculate the index into Table8. */\n-\telse if (lpm->tbl24[tbl24_index].ext_entry == 0) {\n+\telse if (lpm->tbl24[tbl24_index].ext_valid == 0) {\n \t\t/* Search for free tbl8 group. */\n \t\ttbl8_group_index = tbl8_alloc(lpm->tbl8);\n \n@@ -551,6 +563,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \t\t\tlpm->tbl8[i].depth = lpm->tbl24[tbl24_index].depth;\n \t\t\tlpm->tbl8[i].next_hop =\n \t\t\t\t\tlpm->tbl24[tbl24_index].next_hop;\n+\t\t\tlpm->tbl8[i].fwd_class =\n+\t\t\t\t\tlpm->tbl24[tbl24_index].fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\tlpm->tbl8[i].as_num = lpm->tbl24[tbl24_index].as_num;\n+#endif\n \t\t}\n \n \t\ttbl8_index = tbl8_group_start + (ip_masked & 0xFF);\n@@ -561,7 +578,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \t\t\t\t\tlpm->tbl8[i].depth <= depth) {\n \t\t\t\tlpm->tbl8[i].valid = VALID;\n \t\t\t\tlpm->tbl8[i].depth = depth;\n-\t\t\t\tlpm->tbl8[i].next_hop = next_hop;\n+\t\t\t\tlpm->tbl8[i].next_hop = res->next_hop;\n+\t\t\t\tlpm->tbl8[i].fwd_class = res->fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t\tlpm->tbl8[i].as_num = res->as_num;\n+#endif\n \n \t\t\t\tcontinue;\n \t\t\t}\n@@ -573,11 +594,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \t\t * so assign whole structure in one go.\n \t\t */\n \n-\t\tstruct rte_lpm_tbl24_entry new_tbl24_entry = {\n-\t\t\t\t{ .tbl8_gindex = (uint8_t)tbl8_group_index, },\n-\t\t\t\t.valid = VALID,\n-\t\t\t\t.ext_entry = 1,\n+\t\tstruct rte_lpm_tbl_entry new_tbl24_entry = {\n+\t\t\t\t.tbl8_gindex = (uint16_t)tbl8_group_index,\n \t\t\t\t.depth = 0,\n+\t\t\t\t.ext_valid = 1,\n+\t\t\t\t.valid = VALID,\n \t\t};\n \n \t\tlpm->tbl24[tbl24_index] = new_tbl24_entry;\n@@ -595,11 +616,15 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n \n \t\t\tif (!lpm->tbl8[i].valid ||\n \t\t\t\t\tlpm->tbl8[i].depth <= depth) {\n-\t\t\t\tstruct rte_lpm_tbl8_entry new_tbl8_entry = {\n-\t\t\t\t\t.valid = VALID,\n+\t\t\t\tstruct rte_lpm_tbl_entry new_tbl8_entry = {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t\t\t.as_num = res->as_num,\n+#endif\n+\t\t\t\t\t.next_hop = res->next_hop,\n+\t\t\t\t\t.fwd_class = res->fwd_class,\n \t\t\t\t\t.depth = depth,\n-\t\t\t\t\t.next_hop = next_hop,\n-\t\t\t\t\t.valid_group = lpm->tbl8[i].valid_group,\n+\t\t\t\t\t.ext_valid = lpm->tbl8[i].ext_valid,\n+\t\t\t\t\t.valid = VALID,\n \t\t\t\t};\n \n \t\t\t\t/*\n@@ -621,19 +646,19 @@ add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth,\n  */\n int\n rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n-\t\tuint8_t next_hop)\n+\t\tstruct rte_lpm_res *res)\n {\n \tint32_t rule_index, status = 0;\n \tuint32_t ip_masked;\n \n \t/* Check user arguments. */\n-\tif ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM_MAX_DEPTH))\n+\tif ((lpm == NULL) || (res == NULL) || (depth < 1) || (depth > RTE_LPM_MAX_DEPTH))\n \t\treturn -EINVAL;\n \n \tip_masked = ip & depth_to_mask(depth);\n \n \t/* Add the rule to the rule table. */\n-\trule_index = rule_add(lpm, ip_masked, depth, next_hop);\n+\trule_index = rule_add(lpm, ip_masked, depth, res);\n \n \t/* If the is no space available for new rule return error. */\n \tif (rule_index < 0) {\n@@ -641,10 +666,10 @@ rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n \t}\n \n \tif (depth <= MAX_DEPTH_TBL24) {\n-\t\tstatus = add_depth_small(lpm, ip_masked, depth, next_hop);\n+\t\tstatus = add_depth_small(lpm, ip_masked, depth, res);\n \t}\n \telse { /* If depth > RTE_LPM_MAX_DEPTH_TBL24 */\n-\t\tstatus = add_depth_big(lpm, ip_masked, depth, next_hop);\n+\t\tstatus = add_depth_big(lpm, ip_masked, depth, res);\n \n \t\t/*\n \t\t * If add fails due to exhaustion of tbl8 extensions delete\n@@ -665,14 +690,14 @@ rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n  */\n int\n rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n-uint8_t *next_hop)\n+\t\t\tstruct rte_lpm_res *res)\n {\n \tuint32_t ip_masked;\n \tint32_t rule_index;\n \n \t/* Check user arguments. */\n \tif ((lpm == NULL) ||\n-\t\t(next_hop == NULL) ||\n+\t\t(res == NULL) ||\n \t\t(depth < 1) || (depth > RTE_LPM_MAX_DEPTH))\n \t\treturn -EINVAL;\n \n@@ -681,7 +706,11 @@ uint8_t *next_hop)\n \trule_index = rule_find(lpm, ip_masked, depth);\n \n \tif (rule_index >= 0) {\n-\t\t*next_hop = lpm->rules_tbl[rule_index].next_hop;\n+\t\tres->next_hop = lpm->rules_tbl[rule_index].next_hop;\n+\t\tres->fwd_class = lpm->rules_tbl[rule_index].fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\tres->as_num = lpm->rules_tbl[rule_index].as_num;\n+#endif\n \t\treturn 1;\n \t}\n \n@@ -731,7 +760,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t ip_masked,\n \t\t */\n \t\tfor (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) {\n \n-\t\t\tif (lpm->tbl24[i].ext_entry == 0 &&\n+\t\t\tif (lpm->tbl24[i].ext_valid == 0 &&\n \t\t\t\t\tlpm->tbl24[i].depth <= depth ) {\n \t\t\t\tlpm->tbl24[i].valid = INVALID;\n \t\t\t}\n@@ -761,23 +790,30 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t ip_masked,\n \t\t * associated with this rule.\n \t\t */\n \n-\t\tstruct rte_lpm_tbl24_entry new_tbl24_entry = {\n-\t\t\t{.next_hop = lpm->rules_tbl[sub_rule_index].next_hop,},\n-\t\t\t.valid = VALID,\n-\t\t\t.ext_entry = 0,\n+\t\tstruct rte_lpm_tbl_entry new_tbl24_entry = {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t.as_num = lpm->rules_tbl[sub_rule_index].as_num,\n+#endif\n+\t\t\t.next_hop = lpm->rules_tbl[sub_rule_index].next_hop,\n+\t\t\t.fwd_class = lpm->rules_tbl[sub_rule_index].fwd_class,\n \t\t\t.depth = sub_rule_depth,\n+\t\t\t.ext_valid = 0,\n+\t\t\t.valid = VALID,\n \t\t};\n \n-\t\tstruct rte_lpm_tbl8_entry new_tbl8_entry = {\n-\t\t\t.valid = VALID,\n+\t\tstruct rte_lpm_tbl_entry new_tbl8_entry = {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t.as_num = lpm->rules_tbl[sub_rule_index].as_num,\n+#endif\n+\t\t\t.next_hop = lpm->rules_tbl[sub_rule_index].next_hop,\n+\t\t\t.fwd_class = lpm->rules_tbl[sub_rule_index].fwd_class,\n \t\t\t.depth = sub_rule_depth,\n-\t\t\t.next_hop = lpm->rules_tbl\n-\t\t\t[sub_rule_index].next_hop,\n+\t\t\t.valid = VALID,\n \t\t};\n \n \t\tfor (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) {\n \n-\t\t\tif (lpm->tbl24[i].ext_entry == 0 &&\n+\t\t\tif (lpm->tbl24[i].ext_valid == 0 &&\n \t\t\t\t\tlpm->tbl24[i].depth <= depth ) {\n \t\t\t\tlpm->tbl24[i] = new_tbl24_entry;\n \t\t\t}\n@@ -814,7 +850,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t ip_masked,\n  * thus can be recycled\n  */\n static inline int32_t\n-tbl8_recycle_check(struct rte_lpm_tbl8_entry *tbl8, uint32_t tbl8_group_start)\n+tbl8_recycle_check(struct rte_lpm_tbl_entry *tbl8, uint32_t tbl8_group_start)\n {\n \tuint32_t tbl8_group_end, i;\n \ttbl8_group_end = tbl8_group_start + RTE_LPM_TBL8_GROUP_NUM_ENTRIES;\n@@ -891,11 +927,15 @@ delete_depth_big(struct rte_lpm *lpm, uint32_t ip_masked,\n \t}\n \telse {\n \t\t/* Set new tbl8 entry. */\n-\t\tstruct rte_lpm_tbl8_entry new_tbl8_entry = {\n-\t\t\t.valid = VALID,\n-\t\t\t.depth = sub_rule_depth,\n-\t\t\t.valid_group = lpm->tbl8[tbl8_group_start].valid_group,\n+\t\tstruct rte_lpm_tbl_entry new_tbl8_entry = {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t.as_num = lpm->rules_tbl[sub_rule_index].as_num,\n+#endif\n+\t\t\t.fwd_class = lpm->rules_tbl[sub_rule_index].fwd_class,\n \t\t\t.next_hop = lpm->rules_tbl[sub_rule_index].next_hop,\n+\t\t\t.depth = sub_rule_depth,\n+\t\t\t.ext_valid = lpm->tbl8[tbl8_group_start].ext_valid,\n+\t\t\t.valid = VALID,\n \t\t};\n \n \t\t/*\n@@ -923,11 +963,15 @@ delete_depth_big(struct rte_lpm *lpm, uint32_t ip_masked,\n \t}\n \telse if (tbl8_recycle_index > -1) {\n \t\t/* Update tbl24 entry. */\n-\t\tstruct rte_lpm_tbl24_entry new_tbl24_entry = {\n-\t\t\t{ .next_hop = lpm->tbl8[tbl8_recycle_index].next_hop, },\n-\t\t\t.valid = VALID,\n-\t\t\t.ext_entry = 0,\n+\t\tstruct rte_lpm_tbl_entry new_tbl24_entry = {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\t.as_num = lpm->tbl8[tbl8_recycle_index].as_num,\n+#endif\n+\t\t\t.next_hop = lpm->tbl8[tbl8_recycle_index].next_hop,\n+\t\t\t.fwd_class = lpm->tbl8[tbl8_recycle_index].fwd_class,\n \t\t\t.depth = lpm->tbl8[tbl8_recycle_index].depth,\n+\t\t\t.ext_valid = 0,\n+\t\t\t.valid = VALID,\n \t\t};\n \n \t\t/* Set tbl24 before freeing tbl8 to avoid race condition. */\ndiff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h\nindex c299ce2..7c615bc 100644\n--- a/lib/librte_lpm/rte_lpm.h\n+++ b/lib/librte_lpm/rte_lpm.h\n@@ -31,8 +31,8 @@\n  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n  */\n \n-#ifndef _RTE_LPM_H_\n-#define _RTE_LPM_H_\n+#ifndef _RTE_LPM_EXT_H_\n+#define _RTE_LPM_EXT_H_\n \n /**\n  * @file\n@@ -81,57 +81,58 @@ extern \"C\" {\n #define RTE_LPM_RETURN_IF_TRUE(cond, retval)\n #endif\n \n-/** @internal bitmask with valid and ext_entry/valid_group fields set */\n-#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x0300\n+/** @internal bitmask with valid and ext_valid/ext_valid fields set */\n+#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03\n \n /** Bitmask used to indicate successful lookup */\n-#define RTE_LPM_LOOKUP_SUCCESS          0x0100\n+#define RTE_LPM_LOOKUP_SUCCESS          0x01\n+\n+struct rte_lpm_res {\n+\tuint16_t\tnext_hop;\n+\tuint8_t\t\tfwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tuint32_t\tas_num;\n+#endif\n+};\n \n #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN\n-/** @internal Tbl24 entry structure. */\n-struct rte_lpm_tbl24_entry {\n-\t/* Stores Next hop or group index (i.e. gindex)into tbl8. */\n+struct rte_lpm_tbl_entry {\n+\tuint8_t valid\t\t:1;\n+\tuint8_t ext_valid\t:1;\n+\tuint8_t depth\t\t:6;\n+\tuint8_t fwd_class;\n \tunion {\n-\t\tuint8_t next_hop;\n-\t\tuint8_t tbl8_gindex;\n+\t\tuint16_t next_hop;\n+\t\tuint16_t tbl8_gindex;\n \t};\n-\t/* Using single uint8_t to store 3 values. */\n-\tuint8_t valid     :1; /**< Validation flag. */\n-\tuint8_t ext_entry :1; /**< External entry. */\n-\tuint8_t depth     :6; /**< Rule depth. */\n-};\n-\n-/** @internal Tbl8 entry structure. */\n-struct rte_lpm_tbl8_entry {\n-\tuint8_t next_hop; /**< next hop. */\n-\t/* Using single uint8_t to store 3 values. */\n-\tuint8_t valid       :1; /**< Validation flag. */\n-\tuint8_t valid_group :1; /**< Group validation flag. */\n-\tuint8_t depth       :6; /**< Rule depth. */\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tuint32_t as_num;\n+#endif\n };\n #else\n-struct rte_lpm_tbl24_entry {\n-\tuint8_t depth       :6;\n-\tuint8_t ext_entry   :1;\n-\tuint8_t valid       :1;\n+struct rte_lpm_tbl_entry {\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tuint32_t as_num;\n+#endif\n \tunion {\n-\t\tuint8_t tbl8_gindex;\n-\t\tuint8_t next_hop;\n+\t\tuint16_t tbl8_gindex;\n+\t\tuint16_t next_hop;\n \t};\n-};\n-\n-struct rte_lpm_tbl8_entry {\n-\tuint8_t depth       :6;\n-\tuint8_t valid_group :1;\n-\tuint8_t valid       :1;\n-\tuint8_t next_hop;\n+\tuint8_t fwd_class;\n+\tuint8_t\tdepth\t\t:6;\n+\tuint8_t ext_valid\t:1;\n+\tuint8_t\tvalid\t\t:1;\n };\n #endif\n \n /** @internal Rule structure. */\n struct rte_lpm_rule {\n \tuint32_t ip; /**< Rule IP address. */\n-\tuint8_t  next_hop; /**< Rule next hop. */\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tuint32_t as_num;\n+#endif\n+\tuint16_t  next_hop; /**< Rule next hop. */\n+\tuint8_t fwd_class;\n };\n \n /** @internal Contains metadata about the rules table. */\n@@ -148,9 +149,9 @@ struct rte_lpm {\n \tstruct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */\n \n \t/* LPM Tables. */\n-\tstruct rte_lpm_tbl24_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \\\n+\tstruct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \\\n \t\t\t__rte_cache_aligned; /**< LPM tbl24 table. */\n-\tstruct rte_lpm_tbl8_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \\\n+\tstruct rte_lpm_tbl_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \\\n \t\t\t__rte_cache_aligned; /**< LPM tbl8 table. */\n \tstruct rte_lpm_rule rules_tbl[0] \\\n \t\t\t__rte_cache_aligned; /**< LPM rules. */\n@@ -219,7 +220,7 @@ rte_lpm_free(struct rte_lpm *lpm);\n  *   0 on success, negative value otherwise\n  */\n int\n-rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop);\n+rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, struct rte_lpm_res *res);\n \n /**\n  * Check if a rule is present in the LPM table,\n@@ -238,7 +239,7 @@ rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop);\n  */\n int\n rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,\n-uint8_t *next_hop);\n+\t\t\tstruct rte_lpm_res *res);\n \n /**\n  * Delete a rule from the LPM table.\n@@ -277,29 +278,43 @@ rte_lpm_delete_all(struct rte_lpm *lpm);\n  *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit\n  */\n static inline int\n-rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint8_t *next_hop)\n+rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, struct rte_lpm_res *res)\n {\n \tunsigned tbl24_index = (ip >> 8);\n-\tuint16_t tbl_entry;\n-\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tuint64_t tbl_entry;\n+#else\n+\tuint32_t tbl_entry;\n+#endif\n \t/* DEBUG: Check user input arguments. */\n-\tRTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);\n+\tRTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (res == NULL)), -EINVAL);\n \n \t/* Copy tbl24 entry */\n-\ttbl_entry = *(const uint16_t *)&lpm->tbl24[tbl24_index];\n-\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\ttbl_entry = *(const uint64_t *)&lpm->tbl24[tbl24_index];\n+#else\n+\ttbl_entry = *(const uint32_t *)&lpm->tbl24[tbl24_index];\n+#endif\n \t/* Copy tbl8 entry (only if needed) */\n \tif (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==\n \t\t\tRTE_LPM_VALID_EXT_ENTRY_BITMASK)) {\n \n \t\tunsigned tbl8_index = (uint8_t)ip +\n-\t\t\t\t((uint8_t)tbl_entry * RTE_LPM_TBL8_GROUP_NUM_ENTRIES);\n+\t\t\t\t((*(struct rte_lpm_tbl_entry *)&tbl_entry).tbl8_gindex * RTE_LPM_TBL8_GROUP_NUM_ENTRIES);\n \n-\t\ttbl_entry = *(const uint16_t *)&lpm->tbl8[tbl8_index];\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\ttbl_entry = *(const uint64_t *)&lpm->tbl8[tbl8_index];\n+#else\n+\t\ttbl_entry = *(const uint32_t *)&lpm->tbl8[tbl8_index];\n+#endif\n \t}\n-\n-\t*next_hop = (uint8_t)tbl_entry;\n+\tres->next_hop  = ((struct rte_lpm_tbl_entry *)&tbl_entry)->next_hop;\n+\tres->fwd_class = ((struct rte_lpm_tbl_entry *)&tbl_entry)->fwd_class;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tres->as_num\t  = ((struct rte_lpm_tbl_entry *)&tbl_entry)->as_num;\n+#endif\n \treturn (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;\n+\n }\n \n /**\n@@ -322,19 +337,25 @@ rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint8_t *next_hop)\n  *  @return\n  *   -EINVAL for incorrect arguments, otherwise 0\n  */\n-#define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \\\n-\t\trte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)\n+#define rte_lpm_lookup_bulk(lpm, ips, res_tbl, n) \\\n+\t\trte_lpm_lookup_bulk_func(lpm, ips, res_tbl, n)\n \n static inline int\n-rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t * ips,\n-\t\tuint16_t * next_hops, const unsigned n)\n+rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,\n+\t\tstruct rte_lpm_res *res_tbl, const unsigned n)\n {\n \tunsigned i;\n+\tint ret = 0;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\tuint64_t tbl_entry;\n+#else\n+\tuint32_t tbl_entry;\n+#endif\n \tunsigned tbl24_indexes[n];\n \n \t/* DEBUG: Check user input arguments. */\n \tRTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||\n-\t\t\t(next_hops == NULL)), -EINVAL);\n+\t\t\t(res_tbl == NULL)), -EINVAL);\n \n \tfor (i = 0; i < n; i++) {\n \t\ttbl24_indexes[i] = ips[i] >> 8;\n@@ -342,20 +363,32 @@ rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t * ips,\n \n \tfor (i = 0; i < n; i++) {\n \t\t/* Simply copy tbl24 entry to output */\n-\t\tnext_hops[i] = *(const uint16_t *)&lpm->tbl24[tbl24_indexes[i]];\n-\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\ttbl_entry = *(const uint64_t *)&lpm->tbl24[tbl24_indexes[i]];\n+#else\n+\t\ttbl_entry = *(const uint32_t *)&lpm->tbl24[tbl24_indexes[i]];\n+#endif\n \t\t/* Overwrite output with tbl8 entry if needed */\n-\t\tif (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==\n-\t\t\t\tRTE_LPM_VALID_EXT_ENTRY_BITMASK)) {\n+\t\tif (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==\n+\t\t\tRTE_LPM_VALID_EXT_ENTRY_BITMASK)) {\n \n \t\t\tunsigned tbl8_index = (uint8_t)ips[i] +\n-\t\t\t\t\t((uint8_t)next_hops[i] *\n-\t\t\t\t\t RTE_LPM_TBL8_GROUP_NUM_ENTRIES);\n+\t\t\t\t((*(struct rte_lpm_tbl_entry *)&tbl_entry).tbl8_gindex * RTE_LPM_TBL8_GROUP_NUM_ENTRIES);\n \n-\t\t\tnext_hops[i] = *(const uint16_t *)&lpm->tbl8[tbl8_index];\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\t\ttbl_entry = *(const uint64_t *)&lpm->tbl8[tbl8_index];\n+#else\n+\t\t\ttbl_entry = *(const uint32_t *)&lpm->tbl8[tbl8_index];\n+#endif\n \t\t}\n+\t\tres_tbl[i].next_hop\t= ((struct rte_lpm_tbl_entry *)&tbl_entry)->next_hop;\n+\t\tres_tbl[i].fwd_class\t= ((struct rte_lpm_tbl_entry *)&tbl_entry)->next_hop;\n+#ifdef RTE_LIBRTE_LPM_ASNUM\n+\t\tres_tbl[i].as_num\t= ((struct rte_lpm_tbl_entry *)&tbl_entry)->as_num;\n+#endif\n+\t\tret |= 1 << i;\n \t}\n-\treturn 0;\n+\treturn ret;\n }\n \n /* Mask four results. */\n@@ -477,4 +510,4 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, __m128i ip, uint16_t hop[4],\n }\n #endif\n \n-#endif /* _RTE_LPM_H_ */\n+#endif /* _RTE_LPM_EXT_H_ */\n",
    "prefixes": [
        "dpdk-dev",
        "v1",
        "0/3"
    ]
}