@@ -364,6 +364,7 @@ extern function is_dynamic_lsp_address(addr: string): bool
extern function extract_lsp_addresses(address: string): Option<lport_addresses>
extern function extract_addresses(address: string): Option<lport_addresses>
extern function extract_lrp_networks(mac: string, networks: Set<string>): Option<lport_addresses>
+extern function extract_ip_addresses(address: string): Option<lport_addresses>
extern function split_addresses(addr: string): (Set<string>, Set<string>)
@@ -184,6 +184,18 @@ pub fn extract_lrp_networks(mac: &String, networks: &ddlog_std::Set<String>) ->
}
}
+pub fn extract_ip_addresses(address: &String) -> ddlog_std::Option<lport_addresses> {
+ unsafe {
+ let mut laddrs: lport_addresses_c = Default::default();
+ if ovn_c::extract_ip_addresses(string2cstr(address).as_ptr(),
+ &mut laddrs as *mut lport_addresses_c) {
+ ddlog_std::Option::Some{x: laddrs.into_ddlog()}
+ } else {
+ ddlog_std::Option::None
+ }
+ }
+}
+
pub fn ovn_internal_version() -> String {
unsafe {
let s = ovn_c::ovn_get_internal_version();
@@ -623,6 +635,7 @@ mod ovn_c {
pub fn extract_addresses(address: *const raw::c_char, laddrs: *mut lport_addresses_c, ofs: *mut raw::c_int) -> bool;
pub fn extract_lrp_networks__(mac: *const raw::c_char, networks: *const *const raw::c_char,
n_networks: libc::size_t, laddrs: *mut lport_addresses_c) -> bool;
+ pub fn extract_ip_addresses(address: *const raw::c_char, laddrs: *mut lport_addresses_c) -> bool;
pub fn destroy_lport_addresses(addrs: *mut lport_addresses_c);
pub fn is_dynamic_lsp_address(address: *const raw::c_char) -> bool;
pub fn split_addresses(addresses: *const raw::c_char, ip4_addrs: *mut ovs_svec, ipv6_addrs: *mut ovs_svec);
@@ -3350,6 +3350,44 @@ for (CheckLspIsUp[check_lsp_is_up]) {
}
}
+Flow(.logical_datapath = sw._uuid,
+ .stage = s_SWITCH_IN_ARP_ND_RSP(),
+ .priority = 50,
+ .__match = __match,
+ .actions = __actions,
+ .external_ids = stage_hint(sp.lsp._uuid)) :-
+
+ sp in &SwitchPort(.sw = sw, .peer = Some{rp}),
+ rp.is_enabled(),
+ var proxy_ips = {
+ match (sp.lsp.options.get("arp_proxy")) {
+ None -> "",
+ Some {addresses} -> {
+ match (extract_ip_addresses(addresses)) {
+ None -> "",
+ Some{addr} -> {
+ var ip4_addrs = vec_empty();
+ for (ip4 in addr.ipv4_addrs) {
+ ip4_addrs.push("${ip4.addr}")
+ };
+ string_join(ip4_addrs, ",")
+ }
+ }
+ }
+ }
+ },
+ proxy_ips != "",
+ var __match = "arp.op == 1 && arp.tpa == {" ++ proxy_ips ++ "}",
+ var __actions = "eth.dst = eth.src; "
+ "eth.src = ${rp.networks.ea}; "
+ "arp.op = 2; /* ARP reply */ "
+ "arp.tha = arp.sha; "
+ "arp.sha = ${rp.networks.ea}; "
+ "arp.tpa <-> arp.spa; "
+ "outport = inport; "
+ "flags.loopback = 1; "
+ "output;".
+
/* For ND solicitations, we need to listen for both the
* unicast IPv6 address and its all-nodes multicast address,
* but always respond with the unicast IPv6 address. */