int l3_offset;
int l4_offset;
u16 ports[2];
- u16 proto;
+ u8 proto;
if (is_l2_path)
{
/* key[0..3] contains src/dst address and is cleared/set below */
/* Remainder of the key and per-packet non-key data */
- p5tuple_pkt->kv.key[4] = 0;
- p5tuple_pkt->kv.value = 0;
+ p5tuple_pkt->kv_40_8.key[4] = 0;
+ p5tuple_pkt->kv_40_8.value = 0;
+ p5tuple_pkt->pkt.is_ip6 = is_ip6;
if (is_ip6)
{
- clib_memcpy (&p5tuple_pkt->addr,
+ clib_memcpy (&p5tuple_pkt->ip6_addr,
get_ptr_to_offset (b0,
offsetof (ip6_header_t,
src_address) + l3_offset),
- sizeof (p5tuple_pkt->addr));
+ sizeof (p5tuple_pkt->ip6_addr));
proto =
*(u8 *) get_ptr_to_offset (b0,
offsetof (ip6_header_t,
}
else
{
- p5tuple_pkt->kv.key[0] = 0;
- p5tuple_pkt->kv.key[1] = 0;
- p5tuple_pkt->kv.key[2] = 0;
- p5tuple_pkt->kv.key[3] = 0;
- clib_memcpy (&p5tuple_pkt->addr[0].ip4,
+ memset(p5tuple_pkt->l3_zero_pad, 0, sizeof(p5tuple_pkt->l3_zero_pad));
+ clib_memcpy (&p5tuple_pkt->ip4_addr,
get_ptr_to_offset (b0,
offsetof (ip4_header_t,
src_address) + l3_offset),
- sizeof (p5tuple_pkt->addr[0].ip4));
- clib_memcpy (&p5tuple_pkt->addr[1].ip4,
- get_ptr_to_offset (b0,
- offsetof (ip4_header_t,
- dst_address) + l3_offset),
- sizeof (p5tuple_pkt->addr[1].ip4));
+ sizeof (p5tuple_pkt->ip4_addr));
proto =
*(u8 *) get_ptr_to_offset (b0,
offsetof (ip4_header_t,
}
p5tuple_pkt->l4.proto = proto;
+ p5tuple_pkt->l4.is_input = is_input;
+
if (PREDICT_TRUE (offset_within_packet (b0, l4_offset)))
{
p5tuple_pkt->pkt.l4_valid = 1;
*(u8 *) get_ptr_to_offset (b0,
l4_offset + offsetof (icmp46_header_t,
code));
+ p5tuple_pkt->l4.is_slowpath = 1;
}
else if ((IP_PROTOCOL_TCP == proto) || (IP_PROTOCOL_UDP == proto))
{
l4_offset + offsetof (tcp_header_t,
flags));
p5tuple_pkt->pkt.tcp_flags_valid = (proto == IP_PROTOCOL_TCP);
+ p5tuple_pkt->l4.is_slowpath = 0;
}
- /*
- * FIXME: rather than the above conditional, here could
- * be a nice generic mechanism to extract two L4 values:
- *
- * have a per-protocol array of 4 elements like this:
- * u8 offset; to take the byte from, off L4 header
- * u8 mask; to mask it with, before storing
- *
- * this way we can describe UDP, TCP and ICMP[46] semantics,
- * and add a sort of FPM-type behavior for other protocols.
- *
- * Of course, is it faster ? and is it needed ?
- *
- */
+ else
+ {
+ p5tuple_pkt->l4.is_slowpath = 1;
+ }
}
}
always_inline int
-fa_acl_match_addr (ip46_address_t * addr1, ip46_address_t * addr2,
- int prefixlen, int is_ip6)
+fa_acl_match_ip4_addr (ip4_address_t * addr1, ip4_address_t * addr2,
+ int prefixlen)
{
if (prefixlen == 0)
{
/* match any always succeeds */
return 1;
}
- if (is_ip6)
+ uint32_t a1 = clib_net_to_host_u32 (addr1->as_u32);
+ uint32_t a2 = clib_net_to_host_u32 (addr2->as_u32);
+ uint32_t mask0 = 0xffffffff - ((1 << (32 - prefixlen)) - 1);
+ return (a1 & mask0) == a2;
+}
+
+always_inline int
+fa_acl_match_ip6_addr (ip6_address_t * addr1, ip6_address_t * addr2,
+ int prefixlen)
+{
+ if (prefixlen == 0)
{
+ /* match any always succeeds */
+ return 1;
+ }
if (memcmp (addr1, addr2, prefixlen / 8))
{
/* If the starting full bytes do not match, no point in bittwidling the thumbs further */
/* The prefix fits into integer number of bytes, so nothing left to do */
return 1;
}
- }
- else
- {
- uint32_t a1 = clib_net_to_host_u32 (addr1->ip4.as_u32);
- uint32_t a2 = clib_net_to_host_u32 (addr2->ip4.as_u32);
- uint32_t mask0 = 0xffffffff - ((1 << (32 - prefixlen)) - 1);
- return (a1 & mask0) == a2;
- }
}
always_inline int
for (i = 0; i < a->count; i++)
{
r = a->rules + i;
-#ifdef FA_NODE_VERBOSE_DEBUG
- clib_warning("ACL_FA_NODE_DBG acl %d rule %d tag %s", acl_index, i, a->tag);
-#endif
if (is_ip6 != r->is_ipv6)
{
continue;
}
- if (!fa_acl_match_addr
- (&pkt_5tuple->addr[1], &r->dst, r->dst_prefixlen, is_ip6))
+ if (is_ip6) {
+ if (!fa_acl_match_ip6_addr
+ (&pkt_5tuple->ip6_addr[1], &r->dst.ip6, r->dst_prefixlen))
continue;
-
-#ifdef FA_NODE_VERBOSE_DEBUG
- clib_warning
- ("ACL_FA_NODE_DBG acl %d rule %d pkt dst addr %U match rule addr %U/%d",
- acl_index, i, format_ip46_address, &pkt_5tuple->addr[1],
- r->is_ipv6 ? IP46_TYPE_IP6: IP46_TYPE_IP4, format_ip46_address,
- &r->dst, r->is_ipv6 ? IP46_TYPE_IP6: IP46_TYPE_IP4,
- r->dst_prefixlen);
-#endif
-
- if (!fa_acl_match_addr
- (&pkt_5tuple->addr[0], &r->src, r->src_prefixlen, is_ip6))
+ if (!fa_acl_match_ip6_addr
+ (&pkt_5tuple->ip6_addr[0], &r->src.ip6, r->src_prefixlen))
+ continue;
+ } else {
+ if (!fa_acl_match_ip4_addr
+ (&pkt_5tuple->ip4_addr[1], &r->dst.ip4, r->dst_prefixlen))
continue;
+ if (!fa_acl_match_ip4_addr
+ (&pkt_5tuple->ip4_addr[0], &r->src.ip4, r->src_prefixlen))
+ continue;
+ }
-#ifdef FA_NODE_VERBOSE_DEBUG
- clib_warning
- ("ACL_FA_NODE_DBG acl %d rule %d pkt src addr %U match rule addr %U/%d",
- acl_index, i, format_ip46_address, &pkt_5tuple->addr[0],
- r->is_ipv6 ? IP46_TYPE_IP6: IP46_TYPE_IP4, format_ip46_address,
- &r->src, r->is_ipv6 ? IP46_TYPE_IP6: IP46_TYPE_IP4,
- r->src_prefixlen);
- clib_warning
- ("ACL_FA_NODE_DBG acl %d rule %d trying to match pkt proto %d with rule %d",
- acl_index, i, pkt_5tuple->l4.proto, r->proto);
-#endif
if (r->proto)
{
if (pkt_5tuple->l4.proto != r->proto)
u32 * trace_bitmap)
{
acl_main_t *am = p_acl_main;
+ fa_5tuple_t * pkt_5tuple_internal = (fa_5tuple_t *)pkt_5tuple;
+ pkt_5tuple_internal->pkt.lc_index = lc_index;
if (am->use_hash_acl_matching) {
- return hash_multi_acl_match_5tuple(lc_index, (fa_5tuple_t *)pkt_5tuple, is_ip6, r_action,
+ return hash_multi_acl_match_5tuple(lc_index, pkt_5tuple_internal, is_ip6, r_action,
r_acl_pos_p, r_acl_match_p, r_rule_match_p, trace_bitmap);
} else {
- return linear_multi_acl_match_5tuple(lc_index, (fa_5tuple_t *)pkt_5tuple, is_ip6, r_action,
+ return linear_multi_acl_match_5tuple(lc_index, pkt_5tuple_internal, is_ip6, r_action,
r_acl_pos_p, r_acl_match_p, r_rule_match_p, trace_bitmap);
}
}