aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/feature
AgeCommit message (Collapse)AuthorFilesLines
2018-10-03VPP-1426: CLI crash on 'set int feature'Paul Vinciguerra1-1/+1
Change-Id: Ib2221a43347c66940b6b5f71914a451ca4627d2f Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
2018-08-13Multiarch handling in different constructor macrosDamjan Marion1-0/+9
This significantly reduces need for ... in multiarch code. Simply constructor macros will jost create static unused entry if CLIB_MARCH_VARIANT is defined and that will be optimized out by compiler. Change-Id: I17d1c4ac0c903adcfadaa4a07de1b854c7ab14ac Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-07-19Remove unused argument to vlib_feature_nextDamjan Marion1-4/+4
Change-Id: Ieb8b53977fc8484c19780941e232ee072b667de3 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-07-19Cleanup of handoff codeDamjan Marion1-14/+0
- removed handoff-dispatch node - removed some unused buffer metadata fields - enqueue to thread logic moved to inline function Change-Id: I7361e1d88f8cce74cd4fcec90d172eade1855cbd Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-05-27VPP-1294: add missing feature arc constraintDave Barach2-7/+42
the ip4-dhcp-client-detect feature MUST run prior to nat44-out2in, or inbound dhcp broadcast packets will be dropped. Certain dhcp servers answer lease renewal dhcp-request packets with broadcast dhcp-acks, leading to unrecoverable lease loss. In detail, this constraint: VNET_FEATURE_INIT (ip4_snat_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in", .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"), }; doesn't get the job done: ip4-unicast: [17] nat44-out2in [23] ip4-dhcp-client-detect [26] ip4-not-enabled Add a proper constraint: VNET_FEATURE_INIT (ip4_snat_out2in, static) = { .arc_name = "ip4-unicast", .node_name = "nat44-out2in", .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa", "ip4-dhcp-client-detect"), }; and the interface feature order is OK, at least in this regard: ip4-unicast: [17] ip4-dhcp-client-detect [18] nat44-out2in [26] ip4-not-enabled We need to carefully audit (especially) the ip4-unicast feature arc, which has [gasp] 37 features on it! Change-Id: I5e749ead7ab2a25d80839a331de6261e112977ad Signed-off-by: Dave Barach <dave@barachs.net>
2018-05-17Fix failure during enable/disable of featuresMatthew Smith1-3/+3
vnet_feature_enable_disable_with_index() checks the return status of vnet_config_{add,del}_feature(). If the config string heap index returned is the same index that was in use prior to the add/delete, it is concluded that a failure occurred and processing of the feature stops. Sometimes the config index that is returned can legitimately be the same index that was in used before the add/delete. The old list of features can have its heap entry deallocated before a new entry for the new list is allocated. The heap entry for the new list can be the entry that was deallocated while deleting the old one. Make vnet_config_{add,del}_feature() return ~0 on failure. Look for that return value as an indication that an error occurred in vnet_enable_disable_feature_by_index(). Change-Id: I88bb3ff88a76971c1b5e5ece74784ce8ba78373c Signed-off-by: Matthew Smith <mgsmith@netgate.com>
2018-04-27A bit of buffer metadata reshuffling to accommodate flow_idDamjan Marion1-9/+9
Change-Id: I2794384557c6272fe217269b14a9db09eda19220 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-04-09features: don't break linked list, create separate one for arcDamjan Marion3-5/+5
We need to keep original linked list so destructire can remove entries. Change-Id: I5ff5ca0e1a417d88707255207725bba46433c943 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-04-09plugins: unload plugin if early init failsDamjan Marion1-0/+16
Change-Id: I32f68e2ee8f5d32962acdefb0193583f71d342b3 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-04-03reassembly: bug fixesKlement Sekera1-2/+6
This change fixes a bug which would corrupt features infra by making feature infra resistant to double-removal. It also fixes 'out of memory' issue by properly initializing the bihash tables. Change-Id: I78ac03139234a9a0e0b48e7bdfac1c38a0069e82 Signed-off-by: Klement Sekera <ksekera@cisco.com>
2018-03-07features: extend 'feature node not found' warning messageDamjan Marion1-2/+4
Change-Id: I8f45fdb3865e2e0cbb5162ac622c07fec5e42b9d Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-02-26vnet: add vnet_device_input_have_features functionDamjan Marion1-0/+7
Change-Id: I28cfa7f7f5e4938146478c4a5cc5ad18612aadaa Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-01-23VPPAPIGEN: vppapigen replacement in Python PLY.Ole Troan1-1/+1
This is a version of the VPP API generator in Python PLY. It supports the existing language, and has a plugin architecture for generators. Currently C and JSON are supported. Changes: - vl_api_version to option version = "major.minor.patch" - enum support - Added error checking and reporting - import support (removed the C pre-processor) - services (tying request/reply together) Version: option version = "1.0.0"; Enum: enum colours { RED, BLUE = 50, }; define foo { vl_api_colours_t colours; }; Services: service { rpc foo returns foo_reply; rpc foo_dump returns stream foo_details; rpc want_stats returns want_stats_reply events ip4_counters, ip6_counters; }; Future planned features: - unions - bool, text - array support (including length) - proto3 output plugin - Refactor C/C++ generator as a plugin - Refactor Java generator as a plugin Change-Id: Ifa289966c790e1b1a8e2938a91e69331e3a58bdf Signed-off-by: Ole Troan <ot@cisco.com>
2018-01-16Tolerate missing nodes during feature arc initialisationNeale Ranns1-2/+8
Change-Id: Ib0d0b663bf71ce52ead2f81140c710f31f040f89 Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-11-10Break up vpe.apiNeale Ranns2-0/+176
- makes the VAPI generated file more consumable. - VOM build times improve. Change-Id: I838488930bd23a0d3818adfdffdbca3eead382df Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
2017-09-20Add ip6-local feature arcPierre Pfister1-1/+2
ip4-local feature arc existed but not ip6-local one. This patch also adds node name to the 'show ip local' command and fixes a minor include issue in vnet/ip/ip4.h file. Change-Id: I9bb8a7159917d58f89afcce974680de20d946a70 Signed-off-by: Pierre Pfister <ppfister@cisco.com>
2017-08-18feature: exit on misconfigured features (VPP-915)Florin Coras1-3/+7
Change-Id: Ifa11f356d727b69cb121a2bf4cfb9d87883f545d Signed-off-by: Florin Coras <fcoras@cisco.com>
2017-03-17Fix IP feature ordering.Neale Ranns2-18/+0
Drop comes before lookup when enabled. is_first_or_last is not required when setting a feature, the anchor is added in find_config_with_features(). Don't make the PG interfaces automatically L3 enabled, this way we can have tests that check the L3 protocol disbaled behaviour. Change-Id: Icef22a920b27ff9cec6ab2da6b05f05c532cb60f Signed-off-by: Neale Ranns <nranns@cisco.com>
2017-03-17Cache a 'has-features' flag on the adjacency for faster access. Reclaim the ↵Neale Ranns1-0/+2
node_index memeber from the rewrite for space - this is only used for formtting before: ip4-rewrite * * * * 2.66e1 256.00 after: ip4-rewrite * * * * 2.40e1 256.00 Change-Id: Ic397150727cad38811564777419ad6bd26b8a3a6 Signed-off-by: Neale Ranns <nranns@wasa-ucs-11.cisco.com>
2017-03-06features: take device-input buffer advance value directlyDamjan Marion1-27/+35
Change-Id: Ifac7d9134d03d79164ce6f06ae9413279bbaadb3 Signed-off-by: Damjan Marion <damarion@cisco.com>
2017-03-02VPP-648: CLI Memory leak with invalid parameterBilly McFall1-0/+1
After VPP-635 was merged, did one more pass. While the code was waiting to be merged, a few changes were merged to master with the same issue. This is a few additional changes addressing the same issue. See VPP-635. Change-Id: I7abeac5c260c1e2e9d9d318fd1aae24cd6932efc Signed-off-by: Billy McFall <bmcfall@redhat.com>
2016-12-28Reorganize source tree to use single autotools instanceDamjan Marion3-0/+1146
Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion <damarion@cisco.com>
class="cm"> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <vppinfra/bitmap.h> #include <vppinfra/bitops.h> /* for next_with_same_number_of_set_bits */ #include <vppinfra/error.h> /* for ASSERT */ #include <vppinfra/mem.h> #include <vppinfra/os.h> /* for os_panic */ #include <vppinfra/vec.h> #include <vppinfra/zvec.h> /* Consider coding as bitmap, coding = 2^c_0 + 2^c_1 + ... + 2^c_n With c_0 < c_1 < ... < c_n. coding == 0 represents c_n = BITS (uword). Unsigned integers i = 0 ... are represented as follows: 0 <= i < 2^c_0 (i << 1) | (1 << 0) binary: i 1 2^c_0 <= i < 2^c_0 + 2^c_1 (i << 2) | (1 << 1) binary: i 1 0 ... binary: i 0 ... 0 Smaller numbers use less bits. Coding is chosen so that encoding of given histogram of typical values gives smallest number of bits. The number and position of coding bits c_i are used to best fit the histogram of typical values. */ /* Decode given compressed data. Return number of compressed data bits used. */ uword zvec_decode (uword coding, uword zdata, uword * n_zdata_bits) { uword c, d, result, n_bits; uword explicit_end, implicit_end; result = 0; n_bits = 0; while (1) { c = first_set (coding); implicit_end = c == coding; explicit_end = (zdata & 1) & ~implicit_end; d = (zdata >> explicit_end) & (c - 1); if (explicit_end | implicit_end) { result += d; n_bits += min_log2 (c) + explicit_end; break; } n_bits += 1; result += c; coding ^= c; zdata >>= 1; } if (coding == 0) n_bits = BITS (uword); *n_zdata_bits = n_bits; return result; } uword zvec_encode (uword coding, uword data, uword * n_result_bits) { uword c, shift, result; uword explicit_end, implicit_end; /* Data must be in range. Note special coding == 0 would break for data - 1 <= coding. */ ASSERT (data <= coding - 1); shift = 0; while (1) { c = first_set (coding); implicit_end = c == coding; explicit_end = ((data & (c - 1)) == data); if (explicit_end | implicit_end) { uword t = explicit_end & ~implicit_end; result = ((data << t) | t) << shift; *n_result_bits = /* data bits */ (c == 0 ? BITS (uword) : min_log2 (c)) /* shift bits */ + shift + t; return result; } data -= c; coding ^= c; shift++; } /* Never reached. */ ASSERT (0); return ~0; } always_inline uword get_data (void *data, uword data_bytes, uword is_signed) { if (data_bytes == 1) return is_signed ? zvec_signed_to_unsigned (*(i8 *) data) : *(u8 *) data; else if (data_bytes == 2) return is_signed ? zvec_signed_to_unsigned (*(i16 *) data) : *(u16 *) data; else if (data_bytes == 4) return is_signed ? zvec_signed_to_unsigned (*(i32 *) data) : *(u32 *) data; else if (data_bytes == 8) return is_signed ? zvec_signed_to_unsigned (*(i64 *) data) : *(u64 *) data; else { os_panic (); return ~0; } } always_inline void put_data (void *data, uword data_bytes, uword is_signed, uword x) { if (data_bytes == 1) { if (is_signed) *(i8 *) data = zvec_unsigned_to_signed (x); else *(u8 *) data = x; } else if (data_bytes == 2) { if (is_signed) *(i16 *) data = zvec_unsigned_to_signed (x); else *(u16 *) data = x; } else if (data_bytes == 4) { if (is_signed) *(i32 *) data = zvec_unsigned_to_signed (x); else *(u32 *) data = x; } else if (data_bytes == 8) { if (is_signed) *(i64 *) data = zvec_unsigned_to_signed (x); else *(u64 *) data = x; } else { os_panic (); } } always_inline uword * zvec_encode_inline (uword * zvec, uword * zvec_n_bits, uword coding, void *data, uword data_stride, uword n_data, uword data_bytes, uword is_signed) { uword i; i = *zvec_n_bits; while (n_data >= 1) { uword d0, z0, l0; d0 = get_data (data + 0 * data_stride, data_bytes, is_signed); data += 1 * data_stride; n_data -= 1; z0 = zvec_encode (coding, d0, &l0); zvec = clib_bitmap_set_multiple (zvec, i, z0, l0); i += l0; } *zvec_n_bits = i; return zvec; } #define _(TYPE,IS_SIGNED) \ uword * zvec_encode_##TYPE (uword * zvec, \ uword * zvec_n_bits, \ uword coding, \ void * data, \ uword data_stride, \ uword n_data) \ { \ return zvec_encode_inline (zvec, zvec_n_bits, \ coding, \ data, data_stride, n_data, \ /* data_bytes */ sizeof (TYPE), \ /* is_signed */ IS_SIGNED); \ } _(u8, /* is_signed */ 0); _(u16, /* is_signed */ 0); _(u32, /* is_signed */ 0); _(u64, /* is_signed */ 0); _(i8, /* is_signed */ 1); _(i16, /* is_signed */ 1); _(i32, /* is_signed */ 1); _(i64, /* is_signed */ 1); #undef _ always_inline uword coding_max_n_bits (uword coding) { uword n_bits; (void) zvec_decode (coding, 0, &n_bits); return n_bits; } always_inline void zvec_decode_inline (uword * zvec, uword * zvec_n_bits, uword coding, void *data, uword data_stride, uword n_data, uword data_bytes, uword is_signed) { uword i, n_max; i = *zvec_n_bits; n_max = coding_max_n_bits (coding); while (n_data >= 1) { uword d0, z0, l0; z0 = clib_bitmap_get_multiple (zvec, i, n_max); d0 = zvec_decode (coding, z0, &l0); i += l0; put_data (data + 0 * data_stride, data_bytes, is_signed, d0); data += 1 * data_stride; n_data -= 1; } *zvec_n_bits = i; } #define _(TYPE,IS_SIGNED) \ void zvec_decode_##TYPE (uword * zvec, \ uword * zvec_n_bits, \ uword coding, \ void * data, \ uword data_stride, \ uword n_data) \ { \ return zvec_decode_inline (zvec, zvec_n_bits, \ coding, \ data, data_stride, n_data, \ /* data_bytes */ sizeof (TYPE), \ /* is_signed */ IS_SIGNED); \ } _(u8, /* is_signed */ 0); _(u16, /* is_signed */ 0); _(u32, /* is_signed */ 0); _(u64, /* is_signed */ 0); _(i8, /* is_signed */ 1); _(i16, /* is_signed */ 1); _(i32, /* is_signed */ 1); _(i64, /* is_signed */ 1); #undef _ /* Compute number of bits needed to encode given histogram. */ static uword zvec_coding_bits (uword coding, uword * histogram_counts, uword min_bits) { uword n_type_bits, n_bits; uword this_count, last_count, max_count_index; uword i, b, l; n_bits = 0; n_type_bits = 1; last_count = 0; max_count_index = vec_len (histogram_counts) - 1; /* Coding is not large enough to encode given data. */ if (coding <= max_count_index) return ~0; i = 0; while (coding != 0) { b = first_set (coding); l = min_log2 (b); i += b; this_count = histogram_counts[i > max_count_index ? max_count_index : i - 1]; /* No more data to encode? */ if (this_count == last_count) break; /* Last coding is i 0 ... 0 so we don't need an extra type bit. */ if (coding == b) n_type_bits--; n_bits += (this_count - last_count) * (n_type_bits + l); /* This coding cannot be minimal: so return. */ if (n_bits >= min_bits) return ~0; last_count = this_count; coding ^= b; n_type_bits++; } return n_bits; } uword _zvec_coding_from_histogram (void *histogram, uword histogram_len, uword histogram_elt_count_offset, uword histogram_elt_bytes, uword max_value_to_encode, zvec_coding_info_t * coding_return) { uword coding, min_coding; uword min_coding_bits, coding_bits; uword i, n_bits_set, total_count; uword *counts; zvec_histogram_count_t *h_count = histogram + histogram_elt_count_offset; if (histogram_len < 1) { coding_return->coding = 0; coding_return->min_coding_bits = 0; coding_return->n_data = 0; coding_return->n_codes = 0; coding_return->ave_coding_bits = 0; return 0; } total_count = 0; counts = vec_new (uword, histogram_len); for (i = 0; i < histogram_len; i++) { zvec_histogram_count_t this_count = h_count[0]; total_count += this_count; counts[i] = total_count; h_count = (zvec_histogram_count_t *) ((void *) h_count + histogram_elt_bytes); } min_coding = 0; min_coding_bits = ~0; { uword base_coding = max_value_to_encode != ~0 ? (1 + max_value_to_encode) : vec_len (counts); uword max_coding = max_pow2 (2 * base_coding); for (n_bits_set = 1; n_bits_set <= 8; n_bits_set++) { for (coding = pow2_mask (n_bits_set); coding < max_coding; coding = next_with_same_number_of_set_bits (coding)) { coding_bits = zvec_coding_bits (coding, counts, min_coding_bits); if (coding_bits >= min_coding_bits) continue; min_coding_bits = coding_bits; min_coding = coding; } } } if (coding_return) { coding_return->coding = min_coding; coding_return->min_coding_bits = min_coding_bits; coding_return->n_data = total_count; coding_return->n_codes = vec_len (counts); coding_return->ave_coding_bits = (f64) min_coding_bits / (f64) total_count; } vec_free (counts); return min_coding; } u8 * format_zvec_coding (u8 * s, va_list * args) { zvec_coding_info_t *c = va_arg (*args, zvec_coding_info_t *); return format (s, "zvec coding 0x%x, %d elts, %d codes, %d bits total, %.4f ave bits/code", c->coding, c->n_data, c->n_codes, c->min_coding_bits, c->ave_coding_bits); } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */