@@ -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*/
82398239static void
82408240add_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