// A unicast packet arriving on an L3 interface must have a dmac
// matching the interface mac. If interface has STATUS_L3 bit set
// mac filter is already done.
- if (!(*is_l2 || (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)))
+ if ((!*is_l2) && ei &&
+ (!(ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)))
{
u64 dmacs[2];
u8 dmacs_bad[2];
ethernet_header_t *e0;
- ethernet_interface_t *ei0;
e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
dmacs[0] = *(u64 *) e0;
- ei0 = ethernet_get_interface (ðernet_main, hi->hw_if_index);
- if (ei0 && vec_len (ei0->secondary_addrs))
+ if (vec_len (ei->secondary_addrs))
ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
- 1 /* n_packets */ , ei0,
- 1 /* have_sec_dmac */ );
+ 1 /* n_packets */, ei,
+ 1 /* have_sec_dmac */);
else
ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
- 1 /* n_packets */ , ei0,
- 0 /* have_sec_dmac */ );
+ 1 /* n_packets */, ei,
+ 0 /* have_sec_dmac */);
if (dmacs_bad[0])
*error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
}
else
{
for (int j = 0; j < 16; j++)
- if (next[j] == 0)
- slowpath_indices[n_slowpath++] = i + j;
+ {
+ if (next[j] == 0)
+ slowpath_indices[n_slowpath++] = i + j;
+ else if (dmac_check && main_is_l3 && dmacs_bad[i + j])
+ {
+ next[j] = 0;
+ slowpath_indices[n_slowpath++] = i + j;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (dmac_check && main_is_l3)
+ {
+ u8x16 dmac_bad = u8x16_load_unaligned (&dmacs_bad[i]);
+ if (!u8x16_is_all_zero (dmac_bad))
+ {
+ for (int j = 0; j < 16; j++)
+ if (dmacs_bad[i + j])
+ {
+ next[j] = 0;
+ slowpath_indices[n_slowpath++] = i + j;
+ }
+ }
}
}
continue;
}
#endif
- if (main_is_l3 && etype[0] == et_ip4)
+ if (dmac_check && main_is_l3 && dmacs_bad[i])
+ {
+ next[0] = 0;
+ slowpath_indices[n_slowpath++] = i;
+ }
+ else if (main_is_l3 && etype[0] == et_ip4)
next[0] = next_ip4;
else if (main_is_l3 && etype[0] == et_ip6)
next[0] = next_ip6;
}
else
{
- /* untagged packet with not well known etyertype */
+ /* untagged packet with not well known ethertype */
if (last_unknown_etype != etype)
{
last_unknown_etype = etype;
dmacs[0] = *(u64 *) e0;
- if (ei && vec_len (ei->secondary_addrs))
- ethernet_input_inline_dmac_check (hi, dmacs,
- dmacs_bad,
- 1 /* n_packets */ ,
- ei,
- 1 /* have_sec_dmac */ );
- else
- ethernet_input_inline_dmac_check (hi, dmacs,
- dmacs_bad,
- 1 /* n_packets */ ,
- ei,
- 0 /* have_sec_dmac */ );
-
- if (dmacs_bad[0])
- error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
+ if (ei)
+ {
+ if (vec_len (ei->secondary_addrs))
+ ethernet_input_inline_dmac_check (
+ hi, dmacs, dmacs_bad, 1 /* n_packets */, ei,
+ 1 /* have_sec_dmac */);
+ else
+ ethernet_input_inline_dmac_check (
+ hi, dmacs, dmacs_bad, 1 /* n_packets */, ei,
+ 0 /* have_sec_dmac */);
+
+ if (dmacs_bad[0])
+ error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
+ }
skip_dmac_check0:
vlib_buffer_advance (b0, sizeof (ethernet_header_t));
}
else
{
- // a specific outer + specifc innner vlan id, a common case
+ // a specific outer + specific innner vlan id, a common case
// get the qinq table
if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
#undef ethernet_error
};
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ethernet_input_node) = {
.name = "ethernet-input",
/* Takes a vector of packets. */
#undef _
},
};
-/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
void