Harmonize vec/pool_get_aligned object sizes and alignment requests 79/12379/5
authorDave Barach <dbarach@cisco.com>
Thu, 3 May 2018 12:26:39 +0000 (08:26 -0400)
committerFlorin Coras <florin.coras@gmail.com>
Fri, 4 May 2018 15:15:22 +0000 (15:15 +0000)
Object sizes must evenly divide alignment requests, or vice
versa. Otherwise, only the first object will be aligned as
requested.

Three choices: add CLIB_CACHE_LINE_ALIGN_MARK(align_me) at
the end of structures, manually pad to an even divisor or multiple of
the alignment request, or use plain vectors/pools.

static assert for enforcement.

Change-Id: I41aa6ff1a58267301d32aaf4b9cd24678ac1c147
Signed-off-by: Dave Barach <dbarach@cisco.com>
49 files changed:
src/plugins/acl/acl.h
src/plugins/dpdk/device/dpdk.h
src/plugins/dpdk/ipsec/ipsec.h
src/plugins/gtpu/gtpu.h
src/plugins/ioam/analyse/ioam_analyse.h
src/plugins/ioam/export-common/ioam_export.h
src/plugins/ioam/ip6/ioam_cache.h
src/plugins/ioam/udp-ping/udp_ping.h
src/plugins/memif/private.h
src/plugins/pppoe/pppoe.h
src/vlib/unix/input.c
src/vnet/bier/bier_disp_entry.h
src/vnet/bier/bier_disp_table.h
src/vnet/bier/bier_fmask.h
src/vnet/bier/bier_imp.h
src/vnet/bier/bier_table.h
src/vnet/dpo/classify_dpo.h
src/vnet/dpo/l3_proxy_dpo.h
src/vnet/dpo/load_balance.h
src/vnet/dpo/load_balance_map.h
src/vnet/dpo/lookup_dpo.h
src/vnet/dpo/mpls_disposition.h
src/vnet/dpo/mpls_label_dpo.h
src/vnet/dpo/receive_dpo.h
src/vnet/dpo/replicate_dpo.h
src/vnet/fib/ip4_fib.c
src/vnet/fib/ip4_fib.h
src/vnet/fib/ip6_fib.c
src/vnet/fib/mpls_fib.c
src/vnet/fib/mpls_fib.h
src/vnet/geneve/geneve.h
src/vnet/gre/gre.h
src/vnet/ip/ip6.h
src/vnet/ip/ip_source_and_port_range_check.h
src/vnet/ipip/ipip.h
src/vnet/ipsec-gre/ipsec_gre.h
src/vnet/ipsec/ipsec.h
src/vnet/map/map.h
src/vnet/mfib/mfib_itf.h
src/vnet/mfib/mfib_table.h
src/vnet/qos/qos_egress_map.h
src/vnet/sctp/sctp.h
src/vnet/session/session_table.h
src/vnet/udp/udp.h
src/vnet/vxlan-gpe/vxlan_gpe.h
src/vnet/vxlan/vxlan.h
src/vpp/oam/oam.c
src/vppinfra/pool.h
src/vppinfra/vec.h

index 8e7c800..51c5b0c 100644 (file)
@@ -101,6 +101,8 @@ typedef struct
  */
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
   u8 tag[64];
   u32 count;
   acl_rule_t *rules;
@@ -108,6 +110,8 @@ typedef struct
 
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
   u8 tag[64];
   u32 count;
   macip_acl_rule_t *rules;
@@ -127,6 +131,8 @@ typedef struct
  */
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
   fa_5tuple_t mask;
   u32 refcount;
 } ace_mask_type_entry_t;
index bd442bd..f02e718 100644 (file)
@@ -125,6 +125,9 @@ typedef uint16_t dpdk_portid_t;
 
 typedef struct
 {
+  /* Required for vec_validate_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   struct rte_ring *swq;
 
   u64 hqos_field0_slabmask;
@@ -141,6 +144,8 @@ typedef struct
 
 typedef struct
 {
+  /* Required for vec_validate_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   struct rte_ring **swq;
   struct rte_mbuf **pkts_enq;
   struct rte_mbuf **pkts_deq;
index d4c620a..4287a2a 100644 (file)
@@ -127,6 +127,8 @@ typedef struct
 
 typedef struct
 {
+  /* Required for vec_validate_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   struct rte_mempool *crypto_op;
   struct rte_mempool *session_h;
   struct rte_mempool **session_drv;
index b1e677d..6331aa3 100644 (file)
@@ -123,6 +123,9 @@ typedef CLIB_PACKED
 
 typedef struct
 {
+  /* Required for pool_get_aligned  */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /* Rewrite string */
   u8 *rewrite;
 
index ef2865d..881b045 100644 (file)
@@ -96,6 +96,8 @@ typedef struct
 */
 typedef struct ioam_analyser_data_t_
 {
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   u8 is_free;
   u8 pad[3];
 
index 9de0d13..7434768 100644 (file)
@@ -33,6 +33,8 @@
 
 typedef struct ioam_export_buffer
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   /* Allocated buffer */
   u32 buffer_index;
   u64 touched_at;
index 338ed98..3a3cf6a 100644 (file)
@@ -98,6 +98,8 @@
  */
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   ip6_address_t src_address;
   ip6_address_t dst_address;
   u16 src_port;
@@ -122,6 +124,8 @@ typedef struct
  */
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   u32 pool_id;
   u32 pool_index;
   ip6_address_t src_address;
@@ -528,8 +532,7 @@ ioam_cache_ts_table_init (vlib_main_t * vm)
                        CLIB_CACHE_LINE_BYTES);
   vec_validate_aligned (cm->ts_stats, no_of_threads - 1,
                        CLIB_CACHE_LINE_BYTES);
-  vec_validate_aligned (cm->timer_wheels, no_of_threads - 1,
-                       CLIB_CACHE_LINE_BYTES);
+  vec_validate (cm->timer_wheels, no_of_threads - 1);
   cm->lookup_table_nbuckets = IOAM_CACHE_TABLE_DEFAULT_HASH_NUM_BUCKETS;
   cm->lookup_table_nbuckets = 1 << max_log2 (cm->lookup_table_nbuckets);
   cm->lookup_table_size = IOAM_CACHE_TABLE_DEFAULT_HASH_MEMORY_SIZE;
index 26c4201..2c0d214 100644 (file)
@@ -84,6 +84,9 @@ typedef struct
 */
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /** Local source IPv4/6 address to be used. */
   ip46_address_t src;
 
index ad6295e..5c8a919 100644 (file)
@@ -80,6 +80,8 @@ typedef struct
 
 typedef struct
 {
+  /* Required for vec_validate_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   void *shm;
   memif_region_size_t region_size;
   int fd;
index 77bc88f..f010750 100644 (file)
@@ -48,6 +48,9 @@ typedef struct
 
 typedef struct
 {
+  /* Required for pool_get_aligned  */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /* pppoe session_id in HOST byte order */
   u16 session_id;
 
index 0c29844..321e443 100644 (file)
@@ -52,6 +52,7 @@
 
 typedef struct
 {
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   int epoll_fd;
   struct epoll_event *epoll_events;
   int n_epoll_fds;
index 34ca5d4..1647a7e 100644 (file)
  * The BIER dispositon object
  */
 typedef struct bier_disp_entry_t_ {
+    /**
+     * Required for pool_get_aligned
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The DPO contirubted from the per-payload protocol parents
      * on cachline 1.
index 6f9380a..c5b2110 100644 (file)
  */
 typedef struct bier_disp_table_t_
 {
+    /**
+     * Required for pool_get_aligned
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * number of locks on the table
      */
index 81b3923..56930f6 100644 (file)
@@ -97,6 +97,11 @@ typedef enum bier_fmask_flags_t_
  *      for the next lookup
  */
 typedef struct bier_fmask_t_ {
+    /**
+     * Required for pool_get_aligned
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The BIER fmask is a child of a FIB entry in the FIB graph.
      */
index 5b21b06..cdc4dbb 100644 (file)
  * The BIER imposition object
  */
 typedef struct bier_imp_t_ {
+    /**
+     * Required for pool_get_aligned
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The DPO contirubted from the resolving BIER table.
      * One per-IP protocol. This allows us to share a BIER imposition
index a22e2e3..5af275f 100644 (file)
@@ -36,6 +36,12 @@ struct bier_route_update_t_;
  * bit-position. Since this is smal <4096, the table is a flat arry
  */
 typedef struct bier_table_t_ {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * Save the MPLS local label associated with the table
      */
@@ -64,11 +70,6 @@ typedef struct bier_table_t_ {
      */
     index_t *bt_entries;
 
-    /**
-     * Everything before this declaration is unused in the switch path
-     */
-    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
-
     /**
      * The identity/key or the table. we need the hdr_len in the data-path
      */
index 48f4b2b..439727d 100644 (file)
  */
 typedef struct classify_dpo_t
 {
+    /**
+     * required for pool_get_aligned.
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     dpo_proto_t cd_proto;
 
     u32 cd_table_index;
index f17ace5..fcc28b3 100644 (file)
 
 typedef struct l3_proxy_dpo_t_
 {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The Software interface index on which traffic is l3_proxyd
      */
index d37f07d..dd9589f 100644 (file)
@@ -82,6 +82,12 @@ typedef struct load_balance_path_t_ {
  *  - per-route counters
  */
 typedef struct load_balance_t_ {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * number of buckets in the load-balance. always a power of 2.
      */
index f9344c0..82dd36b 100644 (file)
@@ -28,6 +28,12 @@ struct load_balance_map_path_t_;
 /**
  */
 typedef struct load_balance_map_t_ {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The buckets of the map that provide the index to index translation.
      * In the first cacheline.
index 4ebd605..21aecad 100644 (file)
@@ -64,6 +64,12 @@ typedef enum lookup_cast_t_ {
  */
 typedef struct lookup_dpo_t
 {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The FIB, or interface from which to get a FIB, in which to perform
      * the next lookup;
index 9c3cc46..86dd60a 100644 (file)
  */
 typedef struct mpls_disp_dpo_t
 {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * Next DPO in the graph
      */
index 98c88f7..4e032d3 100644 (file)
@@ -66,6 +66,12 @@ extern u8* format_mpls_label_dpo_flags(u8 *s, va_list *args);
  */
 typedef struct mpls_label_dpo_t
 {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The MPLS label header to impose. Outer most label first.
      * Each DPO will occupy one cache line, stuff that many labels in.
index 2420fd7..9ab86a8 100644 (file)
 
 typedef struct receive_dpo_t_
 {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * The Software interface index on which traffic is received
      */
index ccb2563..7b07539 100644 (file)
@@ -52,6 +52,12 @@ extern replicate_main_t replicate_main;
  *  - per-route counters
  */
 typedef struct replicate_t_ {
+    /**
+     * required for pool_get_aligned.
+     *  memebers used in the switch path come first!
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * number of buckets in the replicate.
      */
index ef33246..4ab6b1b 100644 (file)
@@ -108,7 +108,7 @@ ip4_create_fib_with_table_id (u32 table_id,
     ip4_fib_t *v4_fib;
     void *old_heap;
 
-    pool_get_aligned(ip4_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES);
+    pool_get(ip4_main.fibs, fib_table);
     memset(fib_table, 0, sizeof(*fib_table));
 
     old_heap = clib_mem_set_heap (ip4_main.mtrie_mheap);
index 84800eb..7fc2d3f 100644 (file)
@@ -57,6 +57,8 @@ typedef struct ip4_fib_t_
   u32 fwd_classify_table_index;
   u32 rev_classify_table_index;
 
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
 } ip4_fib_t;
 
 extern fib_node_index_t ip4_fib_table_lookup(const ip4_fib_t *fib,
index fa9eb11..da2f1ea 100644 (file)
@@ -60,7 +60,7 @@ create_fib_with_table_id (u32 table_id,
     fib_table_t *fib_table;
     ip6_fib_t *v6_fib;
 
-    pool_get_aligned(ip6_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES);
+    pool_get(ip6_main.fibs, fib_table);
     pool_get_aligned(ip6_main.v6_fibs, v6_fib, CLIB_CACHE_LINE_BYTES);
 
     memset(fib_table, 0, sizeof(*fib_table));
index 1593120..223a0dd 100644 (file)
@@ -92,7 +92,7 @@ mpls_fib_create_with_table_id (u32 table_id,
     mpls_fib_t *mf;
     int i;
 
-    pool_get_aligned(mpls_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES);
+    pool_get(mpls_main.fibs, fib_table);
     pool_get_aligned(mpls_main.mpls_fibs, mf, CLIB_CACHE_LINE_BYTES);
 
     ASSERT((fib_table - mpls_main.fibs) ==
index 9e0c7d7..8d18b00 100644 (file)
 
 typedef struct mpls_fib_t_
 {
+  /**
+   * Required for pool_get_aligned
+   */
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
   /**
    * A hash table of entries. 21 bit key
    * Hash table for reduced memory footprint
index cce57c8..8f028df 100644 (file)
@@ -75,6 +75,9 @@ typedef CLIB_PACKED (struct
 
 typedef struct
 {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /* Rewrite string. $$$$ embed vnet_rewrite header */
   u8 *rewrite;
 
index b3b0b54..416ab30 100644 (file)
@@ -175,6 +175,11 @@ typedef struct
  */
 typedef struct
 {
+  /**
+   * Required for pool_get_aligned
+   */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /**
    * Linkage into the FIB object graph
    */
index 359c461..4b24774 100644 (file)
@@ -66,6 +66,9 @@ typedef struct
 
 typedef struct
 {
+  /* required for pool_get_aligned. */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /* Table ID (hash key) for this FIB. */
   u32 table_id;
 
index b04fe61..ece2ec2 100644 (file)
@@ -101,6 +101,11 @@ typedef struct
  */
 typedef struct protocol_port_range_dpo_t_
 {
+  /**
+   * Required for pool_get_aligned
+   */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /**
    * The number of blocks from the 'block' array below
    * that have rnages configured. We keep this count so that in the data-path
index e9277d8..f52094f 100644 (file)
@@ -68,6 +68,9 @@ typedef enum
  */
 typedef struct
 {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   ipip_mode_t mode;
   ipip_transport_t transport;
   ipip_tunnel_key_t *key;
index 5d56b4e..caf2ecf 100644 (file)
@@ -49,6 +49,8 @@ typedef enum
 */
 typedef struct
 {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   ip4_address_t tunnel_src; /**< tunnel IPv4 src address */
   ip4_address_t tunnel_dst; /**< tunnel IPv4 dst address */
   u32 local_sa;                    /**< local IPSec SA index */
index 0269eb0..bf9fab2 100644 (file)
@@ -242,6 +242,8 @@ typedef struct
 
 typedef struct
 {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   u32 input_sa_index;
   u32 output_sa_index;
   u32 hw_if_index;
index 5700cc1..c304a1e 100644 (file)
@@ -80,6 +80,8 @@ typedef enum
  */
 typedef struct
 {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   ip6_address_t ip6_src;
   ip6_address_t ip6_prefix;
   ip6_address_t *rules;
index fe39c89..295be1b 100644 (file)
  */
 typedef struct mfib_itf_t_
 {
+    /**
+     * Required for pool_get_aligned
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * @brief Forwarding Flags on the entry - checked in the data-path
      */
index 63af25b..b8ade8b 100644 (file)
  */
 typedef struct mfib_table_t_
 {
+    /**
+     * Required for pool_get_aligned
+     */
+    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
     /**
      * A union of the protocol specific FIBs that provide the
      * underlying LPM mechanism.
index f4b282c..92baf6b 100644 (file)
@@ -36,10 +36,15 @@ typedef u32 qos_egress_map_id_t;
  */
 typedef struct qos_egress_map_t_
 {
-    /**
-     * The array of output mapped values;
-     *   output = eq_qos[input-source][input-value]
-     */
+  /**
+   * Required for pool_get_aligned
+   */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
+  /**
+   * The array of output mapped values;
+   *   output = eq_qos[input-source][input-value]
+   */
   qos_bits_t qem_output[QOS_N_SOURCES][256];
 } qos_egress_map_t;
 
index ffe3e1b..5f19566 100644 (file)
@@ -192,6 +192,9 @@ typedef struct _sctp_user_configuration
 
 typedef struct _sctp_connection
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS];        /**< Common transport data. First! */
   sctp_user_configuration_t conn_config; /**< Allows tuning of some SCTP behaviors */
 
index 31b1f64..f7f8c91 100644 (file)
@@ -49,6 +49,8 @@ typedef struct _session_lookup_table
    * byproduct of fib table ids not necessarily being the same for
    * identical fib idices of v4 and v6 fib protos */
   u8 active_fib_proto;
+  /* Required for pool_get_aligned(...) */
+    CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
 } session_table_t;
 
 #define SESSION_TABLE_INVALID_INDEX ((u32)~0)
index 8e3ab9e..c60dea0 100644 (file)
@@ -36,6 +36,8 @@ typedef enum
 
 typedef struct
 {
+  /** Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   transport_connection_t connection;   /**< must be first */
   clib_spinlock_t rx_lock;             /**< rx fifo lock */
   u8 is_connected;                     /**< connected mode */
index 8c0d37e..794ed7e 100644 (file)
@@ -101,6 +101,9 @@ typedef CLIB_PACKED(struct {
  */
 typedef struct
 {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
   /** Rewrite string. $$$$ embed vnet_rewrite header */
   u8 *rewrite;
 
index 8fb031d..3c74bfd 100644 (file)
@@ -66,6 +66,9 @@ typedef CLIB_PACKED(struct {
 }) vxlan6_tunnel_key_t;
 
 typedef struct {
+  /* Required for pool_get_aligned */
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
+
   /* FIB DPO for IP forwarding of VXLAN encap packet */
   dpo_id_t next_dpo;  
 
index ef06120..1579f56 100644 (file)
@@ -26,7 +26,7 @@ init_oam_packet_template (oam_main_t * om, oam_target_t * t)
   ip_csum_t sum;
   u16 csum;
 
-  vec_validate_aligned (t->template, 0, CLIB_CACHE_LINE_BYTES);
+  vec_validate (t->template, 0);
 
   h = t->template;
   memset (h, 0, sizeof (*h));
index 14c6a75..8b39a91 100644 (file)
@@ -190,6 +190,8 @@ do {                                                                    \
   pool_header_t * _pool_var (p) = pool_header (P);                      \
   uword _pool_var (l);                                                  \
                                                                         \
+  STATIC_ASSERT(A==0 || ((A % sizeof(P[0]))==0) || ((sizeof(P[0]) % A) == 0), \
+                "Pool aligned alloc of incorrectly sized object");      \
   _pool_var (l) = 0;                                                    \
   if (P)                                                                \
     _pool_var (l) = vec_len (_pool_var (p)->free_indices);              \
index e2cb24c..a029630 100644 (file)
@@ -411,6 +411,8 @@ do {                                                                                \
 
 #define vec_validate_ha(V,I,H,A)                                       \
 do {                                                                   \
+  STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0) || ((sizeof(V[0]) % A) == 0),\
+                "vector validate aligned on incorrectly sized object"); \
   word _v(i) = (I);                                                    \
   word _v(l) = vec_len (V);                                            \
   if (_v(i) >= _v(l))                                                  \