From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id B46635A64 for ; Mon, 26 Oct 2015 16:40:37 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP; 26 Oct 2015 08:40:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,201,1444719600"; d="scan'208";a="835317407" Received: from unknown (HELO Sent) ([10.217.248.144]) by orsmga002.jf.intel.com with SMTP; 26 Oct 2015 08:40:29 -0700 Received: by Sent (sSMTP sendmail emulation); Mon, 26 Oct 2015 16:39:45 +0200 Date: Mon, 26 Oct 2015 16:39:45 +0100 From: Michal Jastrzebski To: Vladimir Medvedkin Message-ID: <20151026153945.GA9500@MKJASTRX-MOBL> References: <1445608311-8092-1-git-send-email-michalx.k.jastrzebski@intel.com> <20151023162033.GA10036@mhcomputing.net> <562B209A.6030507@mhcomputing.net> <20151026115519.GA7576@MKJASTRX-MOBL> <60ABE07DBB3A454EB7FAD707B4BB1582139CCBF9@IRSMSX109.ger.corp.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) Cc: dev@dpdk.org Subject: Re: [dpdk-dev] [PATCH v1 0/3] lpm: increase number of next hops for lpm (ipv4) X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Oct 2015 15:40:38 -0000 esOn Mon, Oct 26, 2015 at 05:03:31PM +0300, Vladimir Medvedkin wrote: > Hi Michal, > > Forwarding class can help us to classify traffic based on dst prefix, it's > something like Juniper DCU. For example on Juniper MX I can make policy > that install prefix into the FIB with some class and use it on dataplane, > for example with ACL. > On Juniper MX I can make something like that: > #show policy-options > policy-statement community-to-class { > term customer { > from community originate-customer; > then destination-class customer; > } > } > community originate-customer members 12345:11111; > # show routing-options > forwarding-table { > export community-to-class; > } > # show forwarding-options > forwarding-options { > family inet { > filter { > output test-filter; > } > } > } > # show firewall family inet filter test-filter > term 1 { > from { > protocol icmp; > destination-class customer; > } > then { > discard; > } > } > announce route 10.10.10.10/32 next-hop 10.10.10.2 community 12345:11111 > After than on dataplane we have > NPC1( vty)# show route ip lookup 10.10.10.10 > Route Information (10.10.10.10): > interface : xe-1/0/0.0 (328) > Nexthop prefix : - > Nexthop ID : 1048574 > MTU : 0 > Class ID : 129 <- That is "forwarding class" in my implementation > This construction discards all ICMP traffic that goes to dst prefixes which > was originated with community 12345:11111. With this mechanism we can make > on control plane different sophisticated policy to control traffic on > dataplane. > The same with as_num, we can have on dataplane AS number that has > originated that prefix, or another 4-byte number e.g. geo-id. > What issue do you mean? I think it is because of table/pipeline/test > frameworks that doesen't want to compile due to changing API/ABI. You can > turn it off for LPM testing, if my patch will be applied I will make > changes in above-mentioned frameworks. > > Regards, > Vladimir Hi Vladimir, I have an issue with applying Your patch not compilation. This is the error i get: Checking patch config/common_bsdapp... Checking patch config/common_linuxapp... Checking patch lib/librte_lpm/rte_lpm.c... error: while searching for: lpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list); RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl24_entry) != 2); RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl8_entry) != 2); /* Check user arguments. */ if ((name == NULL) || (socket_id < -1) || (max_rules == 0)){ rte_errno = EINVAL; error: patch failed: lib/librte_lpm/rte_lpm.c:159 error: lib/librte_lpm/rte_lpm.c: patch does not apply Checking patch lib/librte_lpm/rte_lpm.h... error: while searching for: #define RTE_LPM_RETURN_IF_TRUE(cond, retval) #endif /** @internal bitmask with valid and ext_entry/valid_group fields set */ #define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x0300 /** Bitmask used to indicate successful lookup */ #define RTE_LPM_LOOKUP_SUCCESS 0x0100 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN /** @internal Tbl24 entry structure. */ struct rte_lpm_tbl24_entry { /* Stores Next hop or group index (i.e. gindex)into tbl8. */ union { uint8_t next_hop; uint8_t tbl8_gindex; }; /* Using single uint8_t to store 3 values. */ uint8_t valid :1; /**< Validation flag. */ uint8_t ext_entry :1; /**< External entry. */ uint8_t depth :6; /**< Rule depth. */ }; /** @internal Tbl8 entry structure. */ struct rte_lpm_tbl8_entry { uint8_t next_hop; /**< next hop. */ /* Using single uint8_t to store 3 values. */ uint8_t valid :1; /**< Validation flag. */ uint8_t valid_group :1; /**< Group validation flag. */ uint8_t depth :6; /**< Rule depth. */ }; #else struct rte_lpm_tbl24_entry { uint8_t depth :6; uint8_t ext_entry :1; uint8_t valid :1; union { uint8_t tbl8_gindex; uint8_t next_hop; }; }; struct rte_lpm_tbl8_entry { uint8_t depth :6; uint8_t valid_group :1; uint8_t valid :1; uint8_t next_hop; }; #endif /** @internal Rule structure. */ struct rte_lpm_rule { uint32_t ip; /**< Rule IP address. */ uint8_t next_hop; /**< Rule next hop. */ }; /** @internal Contains metadata about the rules table. */ error: patch failed: lib/librte_lpm/rte_lpm.h:81 error: lib/librte_lpm/rte_lpm.h: patch does not apply > 2015-10-26 14:57 GMT+03:00 Jastrzebski, MichalX K < > michalx.k.jastrzebski@intel.com>: > > > > -----Original Message----- > > > From: Michal Jastrzebski [mailto:michalx.k.jastrzebski@intel.com] > > > Sent: Monday, October 26, 2015 12:55 PM > > > To: Vladimir Medvedkin > > > Subject: Re: [dpdk-dev] [PATCH v1 0/3] lpm: increase number of next hops > > > for lpm (ipv4) > > > > > > On Sun, Oct 25, 2015 at 08:52:04PM +0300, Vladimir Medvedkin wrote: > > > > Hi all, > > > > > > > > Here my implementation > > > > > > > > Signed-off-by: Vladimir Medvedkin > > > > --- > > > > config/common_bsdapp | 1 + > > > > config/common_linuxapp | 1 + > > > > lib/librte_lpm/rte_lpm.c | 194 > > > > +++++++++++++++++++++++++++++------------------ > > > > lib/librte_lpm/rte_lpm.h | 163 +++++++++++++++++++++++---------------- > > > > 4 files changed, 219 insertions(+), 140 deletions(-) > > > > > > > > diff --git a/config/common_bsdapp b/config/common_bsdapp > > > > index b37dcf4..408cc2c 100644 > > > > --- a/config/common_bsdapp > > > > +++ b/config/common_bsdapp > > > > @@ -344,6 +344,7 @@ CONFIG_RTE_LIBRTE_JOBSTATS=y > > > > # > > > > CONFIG_RTE_LIBRTE_LPM=y > > > > CONFIG_RTE_LIBRTE_LPM_DEBUG=n > > > > +CONFIG_RTE_LIBRTE_LPM_ASNUM=n > > > > > > > > # > > > > # Compile librte_acl > > > > diff --git a/config/common_linuxapp b/config/common_linuxapp > > > > index 0de43d5..1c60e63 100644 > > > > --- a/config/common_linuxapp > > > > +++ b/config/common_linuxapp > > > > @@ -352,6 +352,7 @@ CONFIG_RTE_LIBRTE_JOBSTATS=y > > > > # > > > > CONFIG_RTE_LIBRTE_LPM=y > > > > CONFIG_RTE_LIBRTE_LPM_DEBUG=n > > > > +CONFIG_RTE_LIBRTE_LPM_ASNUM=n > > > > > > > > # > > > > # Compile librte_acl > > > > diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c > > > > index 163ba3c..363b400 100644 > > > > --- a/lib/librte_lpm/rte_lpm.c > > > > +++ b/lib/librte_lpm/rte_lpm.c > > > > @@ -159,9 +159,11 @@ rte_lpm_create(const char *name, int socket_id, > > > int > > > > max_rules, > > > > > > > > lpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list); > > > > > > > > - RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl24_entry) != 2); > > > > - RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl8_entry) != 2); > > > > - > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl_entry) != 8); > > > > +#else > > > > + RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl_entry) != 4); > > > > +#endif > > > > /* Check user arguments. */ > > > > if ((name == NULL) || (socket_id < -1) || (max_rules == 0)){ > > > > rte_errno = EINVAL; > > > > @@ -261,7 +263,7 @@ rte_lpm_free(struct rte_lpm *lpm) > > > > */ > > > > static inline int32_t > > > > rule_add(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth, > > > > - uint8_t next_hop) > > > > + struct rte_lpm_res *res) > > > > { > > > > uint32_t rule_gindex, rule_index, last_rule; > > > > int i; > > > > @@ -282,8 +284,11 @@ rule_add(struct rte_lpm *lpm, uint32_t > > > ip_masked, > > > > uint8_t depth, > > > > > > > > /* If rule already exists update its next_hop > > and > > > > return. */ > > > > if (lpm->rules_tbl[rule_index].ip == > > ip_masked) { > > > > - lpm->rules_tbl[rule_index].next_hop = > > > > next_hop; > > > > - > > > > + lpm->rules_tbl[rule_index].next_hop = > > > > res->next_hop; > > > > + lpm->rules_tbl[rule_index].fwd_class = > > > > res->fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + lpm->rules_tbl[rule_index].as_num = > > > > res->as_num; > > > > +#endif > > > > return rule_index; > > > > } > > > > } > > > > @@ -320,7 +325,11 @@ rule_add(struct rte_lpm *lpm, uint32_t > > > ip_masked, > > > > uint8_t depth, > > > > > > > > /* Add the new rule. */ > > > > lpm->rules_tbl[rule_index].ip = ip_masked; > > > > - lpm->rules_tbl[rule_index].next_hop = next_hop; > > > > + lpm->rules_tbl[rule_index].next_hop = res->next_hop; > > > > + lpm->rules_tbl[rule_index].fwd_class = res->fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + lpm->rules_tbl[rule_index].as_num = res->as_num; > > > > +#endif > > > > > > > > /* Increment the used rules counter for this rule group. */ > > > > lpm->rule_info[depth - 1].used_rules++; > > > > @@ -382,10 +391,10 @@ rule_find(struct rte_lpm *lpm, uint32_t > > > ip_masked, > > > > uint8_t depth) > > > > * Find, clean and allocate a tbl8. > > > > */ > > > > static inline int32_t > > > > -tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8) > > > > +tbl8_alloc(struct rte_lpm_tbl_entry *tbl8) > > > > { > > > > uint32_t tbl8_gindex; /* tbl8 group index. */ > > > > - struct rte_lpm_tbl8_entry *tbl8_entry; > > > > + struct rte_lpm_tbl_entry *tbl8_entry; > > > > > > > > /* Scan through tbl8 to find a free (i.e. INVALID) tbl8 group. > > */ > > > > for (tbl8_gindex = 0; tbl8_gindex < RTE_LPM_TBL8_NUM_GROUPS; > > > > @@ -393,12 +402,12 @@ tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8) > > > > tbl8_entry = &tbl8[tbl8_gindex * > > > > RTE_LPM_TBL8_GROUP_NUM_ENTRIES]; > > > > /* If a free tbl8 group is found clean it and set as > > VALID. > > > > */ > > > > - if (!tbl8_entry->valid_group) { > > > > + if (!tbl8_entry->ext_valid) { > > > > memset(&tbl8_entry[0], 0, > > > > RTE_LPM_TBL8_GROUP_NUM_ENTRIES > > * > > > > sizeof(tbl8_entry[0])); > > > > > > > > - tbl8_entry->valid_group = VALID; > > > > + tbl8_entry->ext_valid = VALID; > > > > > > > > /* Return group index for allocated tbl8 > > group. */ > > > > return tbl8_gindex; > > > > @@ -410,46 +419,50 @@ tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8) > > > > } > > > > > > > > static inline void > > > > -tbl8_free(struct rte_lpm_tbl8_entry *tbl8, uint32_t tbl8_group_start) > > > > +tbl8_free(struct rte_lpm_tbl_entry *tbl8, uint32_t tbl8_group_start) > > > > { > > > > /* Set tbl8 group invalid*/ > > > > - tbl8[tbl8_group_start].valid_group = INVALID; > > > > + tbl8[tbl8_group_start].ext_valid = INVALID; > > > > } > > > > > > > > static inline int32_t > > > > add_depth_small(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, > > > > - uint8_t next_hop) > > > > + struct rte_lpm_res *res) > > > > { > > > > uint32_t tbl24_index, tbl24_range, tbl8_index, tbl8_group_end, > > i, j; > > > > > > > > /* Calculate the index into Table24. */ > > > > tbl24_index = ip >> 8; > > > > tbl24_range = depth_to_range(depth); > > > > + struct rte_lpm_tbl_entry new_tbl_entry = { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + .as_num = res->as_num, > > > > +#endif > > > > + .next_hop = res->next_hop, > > > > + .fwd_class = res->fwd_class, > > > > + .ext_valid = 0, > > > > + .depth = depth, > > > > + .valid = VALID, > > > > + }; > > > > + > > > > > > > > for (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) { > > > > /* > > > > * For invalid OR valid and non-extended tbl 24 > > entries set > > > > * entry. > > > > */ > > > > - if (!lpm->tbl24[i].valid || (lpm->tbl24[i].ext_entry > > == 0 && > > > > + if (!lpm->tbl24[i].valid || (lpm->tbl24[i].ext_valid > > == 0 && > > > > lpm->tbl24[i].depth <= depth)) { > > > > > > > > - struct rte_lpm_tbl24_entry new_tbl24_entry = { > > > > - { .next_hop = next_hop, }, > > > > - .valid = VALID, > > > > - .ext_entry = 0, > > > > - .depth = depth, > > > > - }; > > > > - > > > > /* Setting tbl24 entry in one go to avoid race > > > > * conditions > > > > */ > > > > - lpm->tbl24[i] = new_tbl24_entry; > > > > + lpm->tbl24[i] = new_tbl_entry; > > > > > > > > continue; > > > > } > > > > > > > > - if (lpm->tbl24[i].ext_entry == 1) { > > > > + if (lpm->tbl24[i].ext_valid == 1) { > > > > /* If tbl24 entry is valid and extended > > calculate > > > > the > > > > * index into tbl8. > > > > */ > > > > @@ -461,19 +474,14 @@ add_depth_small(struct rte_lpm *lpm, uint32_t > > > ip, > > > > uint8_t depth, > > > > for (j = tbl8_index; j < tbl8_group_end; j++) { > > > > if (!lpm->tbl8[j].valid || > > > > lpm->tbl8[j].depth <= > > > > depth) { > > > > - struct rte_lpm_tbl8_entry > > > > - new_tbl8_entry = { > > > > - .valid = VALID, > > > > - .valid_group = VALID, > > > > - .depth = depth, > > > > - .next_hop = next_hop, > > > > - }; > > > > + > > > > + new_tbl_entry.ext_valid = > > VALID; > > > > > > > > /* > > > > * Setting tbl8 entry in one > > go to > > > > avoid > > > > * race conditions > > > > */ > > > > - lpm->tbl8[j] = new_tbl8_entry; > > > > + lpm->tbl8[j] = new_tbl_entry; > > > > > > > > continue; > > > > } > > > > @@ -486,7 +494,7 @@ add_depth_small(struct rte_lpm *lpm, uint32_t ip, > > > > uint8_t depth, > > > > > > > > static inline int32_t > > > > add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth, > > > > - uint8_t next_hop) > > > > + struct rte_lpm_res *res) > > > > { > > > > uint32_t tbl24_index; > > > > int32_t tbl8_group_index, tbl8_group_start, tbl8_group_end, > > > > tbl8_index, > > > > @@ -512,7 +520,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > ip_masked, > > > > uint8_t depth, > > > > /* Set tbl8 entry. */ > > > > for (i = tbl8_index; i < (tbl8_index + tbl8_range); > > i++) { > > > > lpm->tbl8[i].depth = depth; > > > > - lpm->tbl8[i].next_hop = next_hop; > > > > + lpm->tbl8[i].next_hop = res->next_hop; > > > > + lpm->tbl8[i].fwd_class = res->fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + lpm->tbl8[i].as_num = res->as_num; > > > > +#endif > > > > lpm->tbl8[i].valid = VALID; > > > > } > > > > > > > > @@ -522,17 +534,17 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > > ip_masked, uint8_t depth, > > > > * so assign whole structure in one go > > > > */ > > > > > > > > - struct rte_lpm_tbl24_entry new_tbl24_entry = { > > > > - { .tbl8_gindex = (uint8_t)tbl8_group_index, }, > > > > - .valid = VALID, > > > > - .ext_entry = 1, > > > > + struct rte_lpm_tbl_entry new_tbl24_entry = { > > > > + .tbl8_gindex = (uint16_t)tbl8_group_index, > > > > .depth = 0, > > > > + .ext_valid = 1, > > > > + .valid = VALID, > > > > }; > > > > > > > > lpm->tbl24[tbl24_index] = new_tbl24_entry; > > > > > > > > }/* If valid entry but not extended calculate the index into > > > > Table8. */ > > > > - else if (lpm->tbl24[tbl24_index].ext_entry == 0) { > > > > + else if (lpm->tbl24[tbl24_index].ext_valid == 0) { > > > > /* Search for free tbl8 group. */ > > > > tbl8_group_index = tbl8_alloc(lpm->tbl8); > > > > > > > > @@ -551,6 +563,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > ip_masked, > > > > uint8_t depth, > > > > lpm->tbl8[i].depth = > > lpm->tbl24[tbl24_index].depth; > > > > lpm->tbl8[i].next_hop = > > > > > > lpm->tbl24[tbl24_index].next_hop; > > > > + lpm->tbl8[i].fwd_class = > > > > + > > lpm->tbl24[tbl24_index].fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + lpm->tbl8[i].as_num = > > > > lpm->tbl24[tbl24_index].as_num; > > > > +#endif > > > > } > > > > > > > > tbl8_index = tbl8_group_start + (ip_masked & 0xFF); > > > > @@ -561,7 +578,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > ip_masked, > > > > uint8_t depth, > > > > lpm->tbl8[i].depth <= depth) { > > > > lpm->tbl8[i].valid = VALID; > > > > lpm->tbl8[i].depth = depth; > > > > - lpm->tbl8[i].next_hop = next_hop; > > > > + lpm->tbl8[i].next_hop = res->next_hop; > > > > + lpm->tbl8[i].fwd_class = > > res->fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + lpm->tbl8[i].as_num = res->as_num; > > > > +#endif > > > > > > > > continue; > > > > } > > > > @@ -573,11 +594,11 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > > ip_masked, uint8_t depth, > > > > * so assign whole structure in one go. > > > > */ > > > > > > > > - struct rte_lpm_tbl24_entry new_tbl24_entry = { > > > > - { .tbl8_gindex = > > (uint8_t)tbl8_group_index, > > > > }, > > > > - .valid = VALID, > > > > - .ext_entry = 1, > > > > + struct rte_lpm_tbl_entry new_tbl24_entry = { > > > > + .tbl8_gindex = > > (uint16_t)tbl8_group_index, > > > > .depth = 0, > > > > + .ext_valid = 1, > > > > + .valid = VALID, > > > > }; > > > > > > > > lpm->tbl24[tbl24_index] = new_tbl24_entry; > > > > @@ -595,11 +616,15 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > > ip_masked, uint8_t depth, > > > > > > > > if (!lpm->tbl8[i].valid || > > > > lpm->tbl8[i].depth <= depth) { > > > > - struct rte_lpm_tbl8_entry > > new_tbl8_entry = { > > > > - .valid = VALID, > > > > + struct rte_lpm_tbl_entry > > new_tbl8_entry = { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + .as_num = res->as_num, > > > > +#endif > > > > + .next_hop = res->next_hop, > > > > + .fwd_class = res->fwd_class, > > > > .depth = depth, > > > > - .next_hop = next_hop, > > > > - .valid_group = > > > > lpm->tbl8[i].valid_group, > > > > + .ext_valid = > > lpm->tbl8[i].ext_valid, > > > > + .valid = VALID, > > > > }; > > > > > > > > /* > > > > @@ -621,19 +646,19 @@ add_depth_big(struct rte_lpm *lpm, uint32_t > > > > ip_masked, uint8_t depth, > > > > */ > > > > int > > > > rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, > > > > - uint8_t next_hop) > > > > + struct rte_lpm_res *res) > > > > { > > > > int32_t rule_index, status = 0; > > > > uint32_t ip_masked; > > > > > > > > /* Check user arguments. */ > > > > - if ((lpm == NULL) || (depth < 1) || (depth > > > RTE_LPM_MAX_DEPTH)) > > > > + if ((lpm == NULL) || (res == NULL) || (depth < 1) || (depth > > > > > RTE_LPM_MAX_DEPTH)) > > > > return -EINVAL; > > > > > > > > ip_masked = ip & depth_to_mask(depth); > > > > > > > > /* Add the rule to the rule table. */ > > > > - rule_index = rule_add(lpm, ip_masked, depth, next_hop); > > > > + rule_index = rule_add(lpm, ip_masked, depth, res); > > > > > > > > /* If the is no space available for new rule return error. */ > > > > if (rule_index < 0) { > > > > @@ -641,10 +666,10 @@ rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, > > > uint8_t > > > > depth, > > > > } > > > > > > > > if (depth <= MAX_DEPTH_TBL24) { > > > > - status = add_depth_small(lpm, ip_masked, depth, > > next_hop); > > > > + status = add_depth_small(lpm, ip_masked, depth, res); > > > > } > > > > else { /* If depth > RTE_LPM_MAX_DEPTH_TBL24 */ > > > > - status = add_depth_big(lpm, ip_masked, depth, > > next_hop); > > > > + status = add_depth_big(lpm, ip_masked, depth, res); > > > > > > > > /* > > > > * If add fails due to exhaustion of tbl8 extensions > > delete > > > > @@ -665,14 +690,14 @@ rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, > > > uint8_t > > > > depth, > > > > */ > > > > int > > > > rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t > > depth, > > > > -uint8_t *next_hop) > > > > + struct rte_lpm_res *res) > > > > { > > > > uint32_t ip_masked; > > > > int32_t rule_index; > > > > > > > > /* Check user arguments. */ > > > > if ((lpm == NULL) || > > > > - (next_hop == NULL) || > > > > + (res == NULL) || > > > > (depth < 1) || (depth > RTE_LPM_MAX_DEPTH)) > > > > return -EINVAL; > > > > > > > > @@ -681,7 +706,11 @@ uint8_t *next_hop) > > > > rule_index = rule_find(lpm, ip_masked, depth); > > > > > > > > if (rule_index >= 0) { > > > > - *next_hop = lpm->rules_tbl[rule_index].next_hop; > > > > + res->next_hop = lpm->rules_tbl[rule_index].next_hop; > > > > + res->fwd_class = lpm->rules_tbl[rule_index].fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + res->as_num = lpm->rules_tbl[rule_index].as_num; > > > > +#endif > > > > return 1; > > > > } > > > > > > > > @@ -731,7 +760,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t > > > > ip_masked, > > > > */ > > > > for (i = tbl24_index; i < (tbl24_index + tbl24_range); > > i++) > > > > { > > > > > > > > - if (lpm->tbl24[i].ext_entry == 0 && > > > > + if (lpm->tbl24[i].ext_valid == 0 && > > > > lpm->tbl24[i].depth <= depth ) > > { > > > > lpm->tbl24[i].valid = INVALID; > > > > } > > > > @@ -761,23 +790,30 @@ delete_depth_small(struct rte_lpm *lpm, > > > uint32_t > > > > ip_masked, > > > > * associated with this rule. > > > > */ > > > > > > > > - struct rte_lpm_tbl24_entry new_tbl24_entry = { > > > > - {.next_hop = > > > > lpm->rules_tbl[sub_rule_index].next_hop,}, > > > > - .valid = VALID, > > > > - .ext_entry = 0, > > > > + struct rte_lpm_tbl_entry new_tbl24_entry = { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + .as_num = > > lpm->rules_tbl[sub_rule_index].as_num, > > > > +#endif > > > > + .next_hop = > > lpm->rules_tbl[sub_rule_index].next_hop, > > > > + .fwd_class = > > > > lpm->rules_tbl[sub_rule_index].fwd_class, > > > > .depth = sub_rule_depth, > > > > + .ext_valid = 0, > > > > + .valid = VALID, > > > > }; > > > > > > > > - struct rte_lpm_tbl8_entry new_tbl8_entry = { > > > > - .valid = VALID, > > > > + struct rte_lpm_tbl_entry new_tbl8_entry = { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + .as_num = > > lpm->rules_tbl[sub_rule_index].as_num, > > > > +#endif > > > > + .next_hop = > > lpm->rules_tbl[sub_rule_index].next_hop, > > > > + .fwd_class = > > > > lpm->rules_tbl[sub_rule_index].fwd_class, > > > > .depth = sub_rule_depth, > > > > - .next_hop = lpm->rules_tbl > > > > - [sub_rule_index].next_hop, > > > > + .valid = VALID, > > > > }; > > > > > > > > for (i = tbl24_index; i < (tbl24_index + tbl24_range); > > i++) > > > > { > > > > > > > > - if (lpm->tbl24[i].ext_entry == 0 && > > > > + if (lpm->tbl24[i].ext_valid == 0 && > > > > lpm->tbl24[i].depth <= depth ) > > { > > > > lpm->tbl24[i] = new_tbl24_entry; > > > > } > > > > @@ -814,7 +850,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t > > > > ip_masked, > > > > * thus can be recycled > > > > */ > > > > static inline int32_t > > > > -tbl8_recycle_check(struct rte_lpm_tbl8_entry *tbl8, uint32_t > > > > tbl8_group_start) > > > > +tbl8_recycle_check(struct rte_lpm_tbl_entry *tbl8, uint32_t > > > > tbl8_group_start) > > > > { > > > > uint32_t tbl8_group_end, i; > > > > tbl8_group_end = tbl8_group_start + > > > RTE_LPM_TBL8_GROUP_NUM_ENTRIES; > > > > @@ -891,11 +927,15 @@ delete_depth_big(struct rte_lpm *lpm, uint32_t > > > > ip_masked, > > > > } > > > > else { > > > > /* Set new tbl8 entry. */ > > > > - struct rte_lpm_tbl8_entry new_tbl8_entry = { > > > > - .valid = VALID, > > > > - .depth = sub_rule_depth, > > > > - .valid_group = > > > > lpm->tbl8[tbl8_group_start].valid_group, > > > > + struct rte_lpm_tbl_entry new_tbl8_entry = { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + .as_num = > > lpm->rules_tbl[sub_rule_index].as_num, > > > > +#endif > > > > + .fwd_class = > > > > lpm->rules_tbl[sub_rule_index].fwd_class, > > > > .next_hop = > > lpm->rules_tbl[sub_rule_index].next_hop, > > > > + .depth = sub_rule_depth, > > > > + .ext_valid = > > lpm->tbl8[tbl8_group_start].ext_valid, > > > > + .valid = VALID, > > > > }; > > > > > > > > /* > > > > @@ -923,11 +963,15 @@ delete_depth_big(struct rte_lpm *lpm, uint32_t > > > > ip_masked, > > > > } > > > > else if (tbl8_recycle_index > -1) { > > > > /* Update tbl24 entry. */ > > > > - struct rte_lpm_tbl24_entry new_tbl24_entry = { > > > > - { .next_hop = > > > > lpm->tbl8[tbl8_recycle_index].next_hop, }, > > > > - .valid = VALID, > > > > - .ext_entry = 0, > > > > + struct rte_lpm_tbl_entry new_tbl24_entry = { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + .as_num = lpm->tbl8[tbl8_recycle_index].as_num, > > > > +#endif > > > > + .next_hop = > > lpm->tbl8[tbl8_recycle_index].next_hop, > > > > + .fwd_class = > > > > lpm->tbl8[tbl8_recycle_index].fwd_class, > > > > .depth = lpm->tbl8[tbl8_recycle_index].depth, > > > > + .ext_valid = 0, > > > > + .valid = VALID, > > > > }; > > > > > > > > /* Set tbl24 before freeing tbl8 to avoid race > > condition. */ > > > > diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h > > > > index c299ce2..7c615bc 100644 > > > > --- a/lib/librte_lpm/rte_lpm.h > > > > +++ b/lib/librte_lpm/rte_lpm.h > > > > @@ -31,8 +31,8 @@ > > > > * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > > > DAMAGE. > > > > */ > > > > > > > > -#ifndef _RTE_LPM_H_ > > > > -#define _RTE_LPM_H_ > > > > +#ifndef _RTE_LPM_EXT_H_ > > > > +#define _RTE_LPM_EXT_H_ > > > > > > > > /** > > > > * @file > > > > @@ -81,57 +81,58 @@ extern "C" { > > > > #define RTE_LPM_RETURN_IF_TRUE(cond, retval) > > > > #endif > > > > > > > > -/** @internal bitmask with valid and ext_entry/valid_group fields set > > */ > > > > -#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x0300 > > > > +/** @internal bitmask with valid and ext_valid/ext_valid fields set */ > > > > +#define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03 > > > > > > > > /** Bitmask used to indicate successful lookup */ > > > > -#define RTE_LPM_LOOKUP_SUCCESS 0x0100 > > > > +#define RTE_LPM_LOOKUP_SUCCESS 0x01 > > > > + > > > > +struct rte_lpm_res { > > > > + uint16_t next_hop; > > > > + uint8_t fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + uint32_t as_num; > > > > +#endif > > > > +}; > > > > > > > > #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN > > > > -/** @internal Tbl24 entry structure. */ > > > > -struct rte_lpm_tbl24_entry { > > > > - /* Stores Next hop or group index (i.e. gindex)into tbl8. */ > > > > +struct rte_lpm_tbl_entry { > > > > + uint8_t valid :1; > > > > + uint8_t ext_valid :1; > > > > + uint8_t depth :6; > > > > + uint8_t fwd_class; > > > > union { > > > > - uint8_t next_hop; > > > > - uint8_t tbl8_gindex; > > > > + uint16_t next_hop; > > > > + uint16_t tbl8_gindex; > > > > }; > > > > - /* Using single uint8_t to store 3 values. */ > > > > - uint8_t valid :1; /**< Validation flag. */ > > > > - uint8_t ext_entry :1; /**< External entry. */ > > > > - uint8_t depth :6; /**< Rule depth. */ > > > > -}; > > > > - > > > > -/** @internal Tbl8 entry structure. */ > > > > -struct rte_lpm_tbl8_entry { > > > > - uint8_t next_hop; /**< next hop. */ > > > > - /* Using single uint8_t to store 3 values. */ > > > > - uint8_t valid :1; /**< Validation flag. */ > > > > - uint8_t valid_group :1; /**< Group validation flag. */ > > > > - uint8_t depth :6; /**< Rule depth. */ > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + uint32_t as_num; > > > > +#endif > > > > }; > > > > #else > > > > -struct rte_lpm_tbl24_entry { > > > > - uint8_t depth :6; > > > > - uint8_t ext_entry :1; > > > > - uint8_t valid :1; > > > > +struct rte_lpm_tbl_entry { > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + uint32_t as_num; > > > > +#endif > > > > union { > > > > - uint8_t tbl8_gindex; > > > > - uint8_t next_hop; > > > > + uint16_t tbl8_gindex; > > > > + uint16_t next_hop; > > > > }; > > > > -}; > > > > - > > > > -struct rte_lpm_tbl8_entry { > > > > - uint8_t depth :6; > > > > - uint8_t valid_group :1; > > > > - uint8_t valid :1; > > > > - uint8_t next_hop; > > > > + uint8_t fwd_class; > > > > + uint8_t depth :6; > > > > + uint8_t ext_valid :1; > > > > + uint8_t valid :1; > > > > }; > > > > #endif > > > > > > > > /** @internal Rule structure. */ > > > > struct rte_lpm_rule { > > > > uint32_t ip; /**< Rule IP address. */ > > > > - uint8_t next_hop; /**< Rule next hop. */ > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + uint32_t as_num; > > > > +#endif > > > > + uint16_t next_hop; /**< Rule next hop. */ > > > > + uint8_t fwd_class; > > > > }; > > > > > > > > /** @internal Contains metadata about the rules table. */ > > > > @@ -148,9 +149,9 @@ struct rte_lpm { > > > > struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< > > Rule > > > > info table. */ > > > > > > > > /* LPM Tables. */ > > > > - struct rte_lpm_tbl24_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \ > > > > + struct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \ > > > > __rte_cache_aligned; /**< LPM tbl24 table. */ > > > > - struct rte_lpm_tbl8_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \ > > > > + struct rte_lpm_tbl_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \ > > > > __rte_cache_aligned; /**< LPM tbl8 table. */ > > > > struct rte_lpm_rule rules_tbl[0] \ > > > > __rte_cache_aligned; /**< LPM rules. */ > > > > @@ -219,7 +220,7 @@ rte_lpm_free(struct rte_lpm *lpm); > > > > * 0 on success, negative value otherwise > > > > */ > > > > int > > > > -rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t > > > > next_hop); > > > > +rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, struct > > > > rte_lpm_res *res); > > > > > > > > /** > > > > * Check if a rule is present in the LPM table, > > > > @@ -238,7 +239,7 @@ rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, > > > uint8_t > > > > depth, uint8_t next_hop); > > > > */ > > > > int > > > > rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t > > depth, > > > > -uint8_t *next_hop); > > > > + struct rte_lpm_res *res); > > > > > > > > /** > > > > * Delete a rule from the LPM table. > > > > @@ -277,29 +278,43 @@ rte_lpm_delete_all(struct rte_lpm *lpm); > > > > * -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on > > lookup > > > > hit > > > > */ > > > > static inline int > > > > -rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint8_t *next_hop) > > > > +rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, struct rte_lpm_res > > *res) > > > > { > > > > unsigned tbl24_index = (ip >> 8); > > > > - uint16_t tbl_entry; > > > > - > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + uint64_t tbl_entry; > > > > +#else > > > > + uint32_t tbl_entry; > > > > +#endif > > > > /* DEBUG: Check user input arguments. */ > > > > - RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), > > > > -EINVAL); > > > > + RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (res == NULL)), - > > > EINVAL); > > > > > > > > /* Copy tbl24 entry */ > > > > - tbl_entry = *(const uint16_t *)&lpm->tbl24[tbl24_index]; > > > > - > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + tbl_entry = *(const uint64_t *)&lpm->tbl24[tbl24_index]; > > > > +#else > > > > + tbl_entry = *(const uint32_t *)&lpm->tbl24[tbl24_index]; > > > > +#endif > > > > /* Copy tbl8 entry (only if needed) */ > > > > if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == > > > > RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { > > > > > > > > unsigned tbl8_index = (uint8_t)ip + > > > > - ((uint8_t)tbl_entry * > > > > RTE_LPM_TBL8_GROUP_NUM_ENTRIES); > > > > + ((*(struct rte_lpm_tbl_entry > > > > *)&tbl_entry).tbl8_gindex * RTE_LPM_TBL8_GROUP_NUM_ENTRIES); > > > > > > > > - tbl_entry = *(const uint16_t *)&lpm->tbl8[tbl8_index]; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + tbl_entry = *(const uint64_t *)&lpm->tbl8[tbl8_index]; > > > > +#else > > > > + tbl_entry = *(const uint32_t *)&lpm->tbl8[tbl8_index]; > > > > +#endif > > > > } > > > > - > > > > - *next_hop = (uint8_t)tbl_entry; > > > > + res->next_hop = ((struct rte_lpm_tbl_entry > > *)&tbl_entry)->next_hop; > > > > + res->fwd_class = ((struct rte_lpm_tbl_entry > > > > *)&tbl_entry)->fwd_class; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + res->as_num = ((struct rte_lpm_tbl_entry > > > > *)&tbl_entry)->as_num; > > > > +#endif > > > > return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT; > > > > + > > > > } > > > > > > > > /** > > > > @@ -322,19 +337,25 @@ rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, > > > > uint8_t *next_hop) > > > > * @return > > > > * -EINVAL for incorrect arguments, otherwise 0 > > > > */ > > > > -#define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \ > > > > - rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n) > > > > +#define rte_lpm_lookup_bulk(lpm, ips, res_tbl, n) \ > > > > + rte_lpm_lookup_bulk_func(lpm, ips, res_tbl, n) > > > > > > > > static inline int > > > > -rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t * > > ips, > > > > - uint16_t * next_hops, const unsigned n) > > > > +rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t > > *ips, > > > > + struct rte_lpm_res *res_tbl, const unsigned n) > > > > { > > > > unsigned i; > > > > + int ret = 0; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + uint64_t tbl_entry; > > > > +#else > > > > + uint32_t tbl_entry; > > > > +#endif > > > > unsigned tbl24_indexes[n]; > > > > > > > > /* DEBUG: Check user input arguments. */ > > > > RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) || > > > > - (next_hops == NULL)), -EINVAL); > > > > + (res_tbl == NULL)), -EINVAL); > > > > > > > > for (i = 0; i < n; i++) { > > > > tbl24_indexes[i] = ips[i] >> 8; > > > > @@ -342,20 +363,32 @@ rte_lpm_lookup_bulk_func(const struct rte_lpm > > > *lpm, > > > > const uint32_t * ips, > > > > > > > > for (i = 0; i < n; i++) { > > > > /* Simply copy tbl24 entry to output */ > > > > - next_hops[i] = *(const uint16_t > > > > *)&lpm->tbl24[tbl24_indexes[i]]; > > > > - > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + tbl_entry = *(const uint64_t > > > > *)&lpm->tbl24[tbl24_indexes[i]]; > > > > +#else > > > > + tbl_entry = *(const uint32_t > > > > *)&lpm->tbl24[tbl24_indexes[i]]; > > > > +#endif > > > > /* Overwrite output with tbl8 entry if needed */ > > > > - if (unlikely((next_hops[i] & > > > > RTE_LPM_VALID_EXT_ENTRY_BITMASK) == > > > > - RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { > > > > + if (unlikely((tbl_entry & > > RTE_LPM_VALID_EXT_ENTRY_BITMASK) > > > > == > > > > + RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { > > > > > > > > unsigned tbl8_index = (uint8_t)ips[i] + > > > > - ((uint8_t)next_hops[i] * > > > > - > > RTE_LPM_TBL8_GROUP_NUM_ENTRIES); > > > > + ((*(struct rte_lpm_tbl_entry > > > > *)&tbl_entry).tbl8_gindex * RTE_LPM_TBL8_GROUP_NUM_ENTRIES); > > > > > > > > - next_hops[i] = *(const uint16_t > > > > *)&lpm->tbl8[tbl8_index]; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + tbl_entry = *(const uint64_t > > > > *)&lpm->tbl8[tbl8_index]; > > > > +#else > > > > + tbl_entry = *(const uint32_t > > > > *)&lpm->tbl8[tbl8_index]; > > > > +#endif > > > > } > > > > + res_tbl[i].next_hop = ((struct rte_lpm_tbl_entry > > > > *)&tbl_entry)->next_hop; > > > > + res_tbl[i].fwd_class = ((struct rte_lpm_tbl_entry > > > > *)&tbl_entry)->next_hop; > > > > +#ifdef RTE_LIBRTE_LPM_ASNUM > > > > + res_tbl[i].as_num = ((struct rte_lpm_tbl_entry > > > > *)&tbl_entry)->as_num; > > > > +#endif > > > > + ret |= 1 << i; > > > > } > > > > - return 0; > > > > + return ret; > > > > } > > > > > > > > /* Mask four results. */ > > > > @@ -477,4 +510,4 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, > > > __m128i ip, > > > > uint16_t hop[4], > > > > } > > > > #endif > > > > > > > > -#endif /* _RTE_LPM_H_ */ > > > > +#endif /* _RTE_LPM_EXT_H_ */ > > > > > > > > 2015-10-24 9:09 GMT+03:00 Matthew Hall : > > > > > > > > > On 10/23/15 9:20 AM, Matthew Hall wrote: > > > > > > > > > >> On Fri, Oct 23, 2015 at 03:51:48PM +0200, Michal Jastrzebski wrote: > > > > >> > > > > >>> From: Michal Kobylinski > > > > >>> > > > > >>> The current DPDK implementation for LPM for IPv4 and IPv6 limits > > the > > > > >>> number of next hops to 256, as the next hop ID is an 8-bit long > > field. > > > > >>> Proposed extension increase number of next hops for IPv4 to 2^24 > > and > > > > >>> also allows 32-bits read/write operations. > > > > >>> > > > > >>> This patchset requires additional change to rte_table library to > > meet > > > > >>> ABI compatibility requirements. A v2 will be sent next week. > > > > >>> > > > > >> > > > > >> I also have a patchset for this. > > > > >> > > > > >> I will send it out as well so we could compare. > > > > >> > > > > >> Matthew. > > > > >> > > > > > > > > > > Sorry about the delay; I only work on DPDK in personal time and not > > as > > > > > part of a job. My patchset is attached to this email. > > > > > > > > > > One possible advantage with my patchset, compared to others, is that > > the > > > > > space problem is fixed in both IPV4 and in IPV6, to prevent asymmetry > > > > > between these two standards, which is something I try to avoid as > > much > > > as > > > > > humanly possible. > > > > > > > > > > This is because my application code is green-field, so I absolutely > > don't > > > > > want to put any ugly hacks or incompatibilities in this code if I can > > > > > possibly avoid it. > > > > > > > > > > Otherwise, I am not necessarily as expert about rte_lpm as some of > > the > > > > > full-time guys, but I think with four or five of us in the thread > > hammering > > > > > out patches we will be able to create something amazing together and > > I > > > am > > > > > very very very very very happy about this. > > > > > > > > > > Matthew. > > > > > > > > > > > > Hi Vladimir, > > Thanks for sharing Your implementation. > > Could You please clarify what as_num and fwd_class fields represent? > > The second issue I have is that Your patch doesn’t want to apply on top of > > current head. Could You check this please? > > > > Best regards > > Michal > >