Skip to content

Commit 8ff9432

Browse files
implement l2-port security for all L3 Ports with L3 PortSec Disabled
1 parent 1f11532 commit 8ff9432

1 file changed

Lines changed: 64 additions & 21 deletions

File tree

northd/northd.c

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8233,13 +8233,12 @@ add_l2only_flood_all(struct ovn_port *p, struct hmap *lflows)
82338233
ds_destroy(&match);
82348234
}
82358235

8236-
/* Allow VIF traffic if and only if eth.src matches the port MAC.
8236+
/* Allow VIF traffic if and only if eth.src matches the port MAC for L2 Only Networks.
82378237
* This preserves MAC anti-spoofing while realxing IP/ARP restrictions.
82388238
*/
82398239
static void
82408240
add_l2only_mac_spoofing_prevention(struct ovn_port *p, struct hmap *lflows, const char* src_mac){
82418241
if (!p || !p->od || !p->nbsp) {
8242-
VLOG_DBG("port is null, skipping...");
82438242
return;
82448243
}
82458244

@@ -8251,8 +8250,6 @@ add_l2only_mac_spoofing_prevention(struct ovn_port *p, struct hmap *lflows, cons
82518250
struct ds action = DS_EMPTY_INITIALIZER;
82528251

82538252
/* Use src_mac as the allowed MAC set for this VIF. */
8254-
VLOG_DBG("Adding mac_spoofing prevention to port %s, mac_address: %s", p->key, src_mac);
8255-
82568253
struct eth_addr ea;
82578254
if (eth_addr_from_string(src_mac, &ea)) {
82588255
ds_clear(&match);
@@ -8289,8 +8286,59 @@ add_l2only_mac_spoofing_prevention(struct ovn_port *p, struct hmap *lflows, cons
82898286
debug_drop_action(),
82908287
&p->nbsp->header_, NULL
82918288
);
8292-
}else {
8293-
VLOG_WARN("invalid mac_address: %s for port %s, skipping mac spoofing prevention...", src_mac, p->key);
8289+
}
8290+
8291+
ds_destroy(&match);
8292+
ds_destroy(&action);
8293+
}
8294+
8295+
/* Allow VIF traffic if and only if eth.src matches the port MAC for L3 Ports.
8296+
* This preserves MAC anti-spoofing while realxing IP/ARP restrictions.
8297+
* Applies only if L3 Port Security is disabled
8298+
*/
8299+
static void
8300+
add_l2_port_sec(struct ovn_port *p, struct hmap *lflows){
8301+
if (!p || !p->od || !p->nbsp) {
8302+
return;
8303+
}
8304+
8305+
if (port_is_l2_only_port(p) || p->nbsp->n_port_security || p->nbsp->type == "localport" || p->nbsp->type == "localnet") {
8306+
return;
8307+
}
8308+
8309+
struct ds match = DS_EMPTY_INITIALIZER;
8310+
struct ds action = DS_EMPTY_INITIALIZER;
8311+
8312+
for(int i=0; i<p->n_lsp_addrs; i++) {
8313+
struct eth_addr ea;
8314+
char *src_mac = p->lsp_addrs[i].ea_s;
8315+
/* Use src_mac as the allowed MAC set for this VIF. */
8316+
if (eth_addr_from_string(src_mac, &ea)) {
8317+
VLOG_INFO("Adding flows for src_mac");
8318+
ds_clear(&match);
8319+
ds_clear(&action);
8320+
ds_put_format(&match, "inport == \"%s\" && eth.src != %s", p->key, src_mac);
8321+
ds_put_format(&action, "%s=1; next;", REGBIT_PORT_SEC_DROP);
8322+
ovn_lflow_add_with_hint(
8323+
lflows, p->od,
8324+
S_SWITCH_IN_CHECK_PORT_SEC,
8325+
110,
8326+
ds_cstr(&match),
8327+
ds_cstr(&action),
8328+
&p->nbsp->header_, NULL
8329+
);
8330+
8331+
/* ARP: ensure arp.sha matches MAC */
8332+
ds_clear(&match);
8333+
ds_put_format(&match, "inport == \"%s\" && eth.type == 0x0806 && arp.sha != %s", p->key, src_mac);
8334+
ovn_lflow_add_with_hint(lflows, p->od,
8335+
S_SWITCH_IN_CHECK_PORT_SEC,
8336+
110,
8337+
ds_cstr(&match),
8338+
ds_cstr(&action),
8339+
&p->nbsp->header_, NULL
8340+
);
8341+
}
82948342
}
82958343

82968344
ds_destroy(&match);
@@ -16274,29 +16322,24 @@ build_lswitch_and_lrouter_flows(
1627416322
*
1627516323
* Both are low/specific priority so the standard pipeline keeps
1627616324
* taking precedence when applicable. */
16277-
VLOG_DBG("processing l2_only ports...");
1627816325
HMAP_FOR_EACH (op, key_node, lsi.ls_ports) {
1627916326
if (!op || !op->od || !op->nbsp) {
16280-
VLOG_DBG("port is null, skipping.");
16281-
continue;
16282-
}
16283-
if (!port_is_l2_only_port(op)) {
16284-
VLOG_DBG("port is not l2_only, skipping.");
1628516327
continue;
1628616328
}
16287-
16288-
VLOG_DBG("L2-only VIF detected on %s; adding port-sec bypass + uu fallback",
16289-
op->json_key);
1629016329

1629116330
bool allow_forged_mac = smap_get_bool(&op->nbsp->external_ids, "pf9-allow-mac-forged-transmits", false);
16292-
char *src_mac = smap_get_def(&op->nbsp->external_ids, "pf9-l2port-src-mac", "");
1629316331

16294-
VLOG_DBG("port: %s; src_mac: %s; allow_forged_mac: %s", op->key, src_mac, allow_forged_mac ? "true" : "false");
16332+
if (port_is_l2_only_port(op)) {
16333+
char *src_mac = smap_get_def(&op->nbsp->external_ids, "pf9-l2port-src-mac", "");
1629516334

16296-
add_minimal_portsec_bypass(op, lsi.lflows);
16297-
add_l2only_flood_all(op, lsi.lflows);
16298-
if (!allow_forged_mac && src_mac && src_mac[0]) {
16299-
add_l2only_mac_spoofing_prevention(op, lflows, src_mac);
16335+
add_minimal_portsec_bypass(op, lsi.lflows);
16336+
add_l2only_flood_all(op, lsi.lflows);
16337+
if (!allow_forged_mac && src_mac && src_mac[0]) {
16338+
add_l2only_mac_spoofing_prevention(op, lflows, src_mac);
16339+
}
16340+
}else if (!allow_forged_mac && !op->nbsp->n_port_security && strcmp(op->nbsp->type, "localport") && strcmp(op->nbsp->type, "localnet")){
16341+
// L2 Port Security applicable only if L3 Port Security is disabled AND allow_forged_mac is false AND Port type != "localport" or "localnet"
16342+
add_l2_port_sec(op, lflows);
1630016343
}
1630116344
}
1630216345
stopwatch_stop(LFLOWS_PORTS_STOPWATCH_NAME, time_msec());

0 commit comments

Comments
 (0)