[qca-nss-ecm] Use the common hierarchy construct fucntion for IPv6
* Removed the IPv6 specific hierarchy construct function.
* Reworked the ecm_interface version of the function to be used
by both IPv4 and IPv6.
* Implement a new ARP request send function.
Change-Id: I29f8bf979d40a9ad437dc0ee7e7c623b021967e5
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
diff --git a/ecm_interface.c b/ecm_interface.c
index cb9b753..4147be3 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -595,6 +595,112 @@
}
EXPORT_SYMBOL(ecm_interface_route_release);
+#ifdef ECM_IPV6_ENABLE
+/*
+ * ecm_interface_send_neighbour_solicitation()
+ * Issue an IPv6 Neighbour soliciation request.
+ */
+void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
+{
+ struct in6_addr dst_addr, src_addr;
+ struct in6_addr mc_dst_addr;
+ struct rt6_info *rt6i;
+ struct neighbour *neigh;
+ ip_addr_t ecm_mc_dst_addr, ecm_src_addr;
+ struct net *netf = dev_net(dev);
+ int ret;
+
+ char __attribute__((unused)) dst_addr_str[ECM_IP_ADDR_STRING_BUFFER_SIZE];
+ char __attribute__((unused)) mc_dst_addr_str[ECM_IP_ADDR_STRING_BUFFER_SIZE];
+ char __attribute__((unused)) src_addr_str[ECM_IP_ADDR_STRING_BUFFER_SIZE];
+
+ /*
+ * Find source and destination addresses in Linux format. We need
+ * mcast destination address as well.
+ */
+ ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
+ addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
+ ret = ipv6_dev_get_saddr(netf, dev, &dst_addr, 0, &src_addr);
+
+ /*
+ * IP address in string format for debug
+ */
+ ecm_ip_addr_to_string(dst_addr_str, addr);
+ ECM_NIN6_ADDR_TO_IP_ADDR(ecm_mc_dst_addr, mc_dst_addr);
+ ecm_ip_addr_to_string(mc_dst_addr_str, ecm_mc_dst_addr);
+ ECM_NIN6_ADDR_TO_IP_ADDR(ecm_src_addr, src_addr);
+ ecm_ip_addr_to_string(src_addr_str, ecm_src_addr);
+
+ /*
+ * Find the route entry
+ */
+ rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
+ if (!rt6i) {
+ DEBUG_TRACE("IPv6 Route lookup failure for destination IPv6 address %s\n", dst_addr_str);
+ return;
+ }
+
+ /*
+ * Find the neighbor entry
+ */
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
+ neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
+#else
+ neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
+#endif
+ if (neigh == NULL) {
+ DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address %s\n", dst_addr_str);
+ dst_release(&rt6i->dst);
+ return;
+ }
+
+ /*
+ * Issue a Neighbour soliciation request
+ */
+ DEBUG_TRACE("Issue Neighbour solicitation request\n");
+ ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
+ neigh_release(neigh);
+ dst_release(&rt6i->dst);
+}
+EXPORT_SYMBOL(ecm_interface_send_neighbour_solicitation);
+#endif
+
+/*
+ * ecm_interface_send_arp_request()
+ * Issue and ARP request.
+ */
+void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr)
+{
+ /*
+ * Possible ARP does not know the address yet
+ */
+ __be32 ipv4_addr;
+ __be32 src_ip;
+
+ /*
+ * Issue an ARP request for it, select the src_ip from which to issue the request.
+ */
+ ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
+ src_ip = inet_select_addr(dest_dev, ipv4_addr, RT_SCOPE_LINK);
+ if (!src_ip) {
+ DEBUG_TRACE("Failed to lookup IP for %pI4\n", &ipv4_addr);
+ return;
+ }
+
+ /*
+ * If we have a GW for this address, then we have to send ARP request to the GW
+ */
+ if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
+ ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
+ }
+
+ DEBUG_TRACE("Send ARP for %pI4 using src_ip as %pI4\n", &ipv4_addr, &src_ip);
+ arp_send(ARPOP_REQUEST, ETH_P_ARP, ipv4_addr, dest_dev, src_ip, NULL, NULL, NULL);
+
+ return;
+}
+EXPORT_SYMBOL(ecm_interface_send_arp_request);
+
#ifdef ECM_INTERFACE_PPP_ENABLE
/*
* ecm_interface_skip_l2tp_pptp()
@@ -2198,11 +2304,14 @@
*
* IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
* they will be created and added automatically to the database.
- *
- * GGG TODO Make this function work for IPv6!!!!!!!!!!!!!!
*/
-int32_t ecm_interface_heirarchy_construct(struct ecm_db_iface_instance *interfaces[], ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, int packet_protocol,
- struct net_device *given_dest_dev, bool is_routed, struct net_device *given_src_dev, uint8_t *dest_node_addr, uint8_t *src_node_addr)
+int32_t ecm_interface_heirarchy_construct(struct ecm_db_iface_instance *interfaces[],
+ ip_addr_t packet_src_addr,
+ ip_addr_t packet_dest_addr,
+ int ip_version, int packet_protocol,
+ struct net_device *given_dest_dev,
+ bool is_routed, struct net_device *given_src_dev,
+ uint8_t *dest_node_addr, uint8_t *src_node_addr)
{
int protocol;
ip_addr_t src_addr;
@@ -2222,8 +2331,19 @@
protocol = packet_protocol;
ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
- DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_DOT_FMT " to dest_addr: " ECM_IP_ADDR_DOT_FMT ", protocol: %d\n",
- ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol);
+
+ if (ip_version == 4) {
+ DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_DOT_FMT " to dest_addr: " ECM_IP_ADDR_DOT_FMT ", protocol: %d\n",
+ ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol);
+#ifdef ECM_IPV6_ENABLE
+ } else if (ip_version == 6) {
+ DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_OCTAL_FMT " to dest_addr: " ECM_IP_ADDR_OCTAL_FMT ", protocol: %d\n",
+ ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol);
+#endif
+ } else {
+ DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
+ return ECM_DB_IFACE_HEIRARCHY_MAX;
+ }
/*
* Get device to reach the given destination address.
@@ -2258,12 +2378,17 @@
* PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
* E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
*/
- if (dest_dev && from_local_addr && (protocol == IPPROTO_IPV6)) {
- dev_put(dest_dev);
- dest_dev = given_dest_dev;
- if (dest_dev) {
- dev_hold(dest_dev);
- DEBUG_TRACE("HACK: IPV6 tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
+ if (dest_dev && from_local_addr) {
+ if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
+ ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
+ dev_put(dest_dev);
+ dest_dev = given_dest_dev;
+ if (dest_dev) {
+ dev_hold(dest_dev);
+ DEBUG_TRACE("HACK: %s tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n",
+ (ip_version == 4) ? "IPV6" : "IPIP",
+ ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
+ }
}
}
if (!dest_dev) {
@@ -2306,14 +2431,20 @@
* PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
* E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
*/
- if (src_dev && from_local_addr && (protocol == IPPROTO_IPV6)) {
- dev_put(src_dev);
- src_dev = given_src_dev;
- if (src_dev) {
- dev_hold(src_dev);
- DEBUG_TRACE("HACK: IPV6 tunnel packet with src_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(src_addr), src_dev, src_dev->name);
+ if (src_dev && from_local_addr) {
+ if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
+ ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
+ dev_put(src_dev);
+ src_dev = given_src_dev;
+ if (src_dev) {
+ dev_hold(src_dev);
+ DEBUG_TRACE("HACK: %s tunnel packet with src_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n",
+ (ip_version == 4) ? "IPV6" : "IPIP",
+ ECM_IP_ADDR_TO_OCTAL(src_addr), src_dev, src_dev->name);
+ }
}
}
+
if (!src_dev) {
DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
dev_put(dest_dev);
@@ -2328,7 +2459,8 @@
*/
if (src_dev == dest_dev) {
DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
- if ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)) {
+ if (((ip_version == 4) && ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)))
+ || ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
/*
* This happens from the input hook
* We do not want to create a connection entry for this
@@ -2432,44 +2564,16 @@
ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
uint8_t mac_addr[ETH_ALEN];
if (!ecm_interface_mac_addr_get(dest_addr, mac_addr, &on_link, gw_addr)) {
- /*
- * Possible ARP does not know the address yet
- */
- DEBUG_INFO("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
- if (ECM_IP_ADDR_IS_V4(dest_addr)) {
- __be32 ipv4_addr;
- __be32 src_ip;
-
- /*
- * Issue an ARP request for it, select the src_ip from which to issue the request.
- */
- ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
- src_ip = inet_select_addr(dest_dev, ipv4_addr, RT_SCOPE_LINK);
- if (!src_ip) {
- DEBUG_TRACE("failed to lookup IP for %pI4\n", &ipv4_addr);
-
- dev_put(src_dev);
- dev_put(dest_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
-
- /*
- * If we have a GW for this address, then we have to send ARP request to the GW
- */
- if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
- ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
- }
-
- DEBUG_TRACE("Send ARP for %pI4 using src_ip as %pI4\n", &ipv4_addr, &src_ip);
- arp_send(ARPOP_REQUEST, ETH_P_ARP, ipv4_addr, dest_dev, src_ip, NULL, NULL, NULL);
+ if (ip_version == 4) {
+ DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
+ ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
}
-
- DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
+#ifdef ECM_IPV6_ENABLE
+ if (ip_version == 6) {
+ DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
+ ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
+ }
+#endif
dev_put(src_dev);
dev_put(dest_dev);
@@ -2539,18 +2643,10 @@
*/
if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr,
&dest_on_link, dest_gw_addr)) {
- __be32 ipv4_addr = 0;
- __be32 src_ip = 0;
- DEBUG_WARN("Unable to obtain MAC address for "
- ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
-
/*
- * Issue an ARP request, select the src_ip from which to issue the request.
- */
-
- /*
- * find proper interfce from which to issue ARP
+ * Find proper interfce from which to issue ARP
+ * or neighbour solicitation packet.
*/
if (dest_dev_master) {
master_dev = dest_dev_master;
@@ -2564,33 +2660,16 @@
dev_put(dest_dev_master);
}
- ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
- src_ip = inet_select_addr(master_dev, ipv4_addr, RT_SCOPE_LINK);
- if (!src_ip) {
- DEBUG_TRACE("failed to lookup IP for %pI4\n", &ipv4_addr);
-
- dev_put(src_dev);
- dev_put(dest_dev);
- dev_put(master_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
+ if (ip_version == 4) {
+ DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
+ ecm_interface_send_arp_request(dest_dev, dest_addr, dest_on_link, dest_gw_addr);
}
-
- /*
- * If we have a GW for this address, then we have to send ARP request to the GW
- */
- if (!dest_on_link && !ECM_IP_ADDR_IS_NULL(dest_gw_addr)) {
- ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_gw_addr);
+#ifdef ECM_IPV6_ENABLE
+ if (ip_version == 6) {
+ DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",ECM_IP_ADDR_TO_OCTAL(dest_addr));
+ ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
}
-
- DEBUG_TRACE("Send ARP for %pI4 using src_ip as %pI4\n", &ipv4_addr, &src_ip);
- arp_send(ARPOP_REQUEST, ETH_P_ARP, ipv4_addr, master_dev, src_ip, NULL, NULL, NULL);
-
-
+#endif
dev_put(src_dev);
dev_put(dest_dev);
dev_put(master_dev);
@@ -2603,9 +2682,16 @@
}
}
- next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
- &src_addr_32, &dest_addr_32,
- htons((uint16_t)ETH_P_IP), dest_dev);
+ if (ip_version == 4) {
+ next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
+ &src_addr_32, &dest_addr_32,
+ htons((uint16_t)ETH_P_IP), dest_dev);
+ } else if (ip_version == 6) {
+ next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
+ src_addr, dest_addr,
+ htons((uint16_t)ETH_P_IPV6), dest_dev);
+ }
+
if (next_dev && netif_carrier_ok(next_dev)) {
dev_hold(next_dev);
} else {
diff --git a/ecm_interface.h b/ecm_interface.h
index afeb327..de509e1 100644
--- a/ecm_interface.h
+++ b/ecm_interface.h
@@ -42,9 +42,12 @@
bool ecm_interface_mac_addr_get(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr);
bool ecm_interface_find_route_by_addr(ip_addr_t addr, struct ecm_interface_route *ecm_rt);
void ecm_interface_route_release(struct ecm_interface_route *rt);
+#ifdef ECM_IPV6_ENABLE
+void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr);
+#endif
+void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr);
bool ecm_interface_skip_l2tp_pptp(struct sk_buff *skb, const struct net_device *out);
struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct net_device *dev);
-int32_t ecm_interface_heirarchy_construct(struct ecm_db_iface_instance *interfaces[], ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, int packet_protocol, struct net_device *given_dest_dev, bool is_routed, struct net_device *given_src_dev, uint8_t *dest_node_addr, uint8_t *src_node_addr);
#ifdef ECM_MULTICAST_ENABLE
int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_db_iface_instance *interfaces, struct net_device *in_dev, ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t maxvif, uint32_t *dst_dev, uint32_t *to_interface_first);
@@ -58,6 +61,13 @@
bool ecm_interface_multicast_check_for_br_dev(uint32_t dest_if[], uint8_t max_if);
#endif
+int32_t ecm_interface_heirarchy_construct(struct ecm_db_iface_instance *interfaces[],
+ ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr,
+ int ip_version, int packet_protocol,
+ struct net_device *given_dest_dev, bool is_routed,
+ struct net_device *given_src_dev,
+ uint8_t *dest_node_addr, uint8_t *src_node_addr);
+void ecm_interface_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes);
struct net_device *ecm_interface_dev_find_by_addr(ip_addr_t addr, bool *from_local_addr);
void ecm_interface_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes);
diff --git a/ecm_types.h b/ecm_types.h
index d214e2a..7a94c73 100644
--- a/ecm_types.h
+++ b/ecm_types.h
@@ -52,6 +52,8 @@
#define ECM_IP_ADDR_NULL {0, 0, 0, 0}
+#define ECM_IP_ADDR_STRING_BUFFER_SIZE 40
+
/*
* Type checking functions for various forms of IP address
* Placing these in a macro, enables the compiler to check
diff --git a/frontends/nss/ecm_front_end_ipv6.c b/frontends/nss/ecm_front_end_ipv6.c
index 099de20..6f397d7 100644
--- a/frontends/nss/ecm_front_end_ipv6.c
+++ b/frontends/nss/ecm_front_end_ipv6.c
@@ -202,613 +202,6 @@
extern int nf_ct_tcp_be_liberal;
/*
- * ecm_front_end_ipv6_send_neighbour_solicitation()
- * Issue an IPv6 Neighbour soliciation request.
- */
-void ecm_front_end_ipv6_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
-{
- struct in6_addr dst_addr, src_addr;
- struct in6_addr mc_dst_addr;
- struct rt6_info *rt6i;
- struct neighbour *neigh;
- ip_addr_t ecm_multicast_dst_addr, ecm_src_addr;
- struct net *netf = dev_net(dev);
- int ret;
-
- char __attribute__((unused)) dst_addr_str[40];
- char __attribute__((unused)) mc_dst_addr_str[40];
- char __attribute__((unused)) src_addr_str[40];
-
- /*
- * Find source and destination addresses in Linux format. We need
- * mcast destination address as well.
- */
- ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
- addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
- ret = ipv6_dev_get_saddr(netf, dev, &dst_addr, 0, &src_addr);
-
- /*
- * IP address in string format for debug
- */
- ecm_ip_addr_to_string(dst_addr_str, addr);
- ECM_NIN6_ADDR_TO_IP_ADDR(ecm_multicast_dst_addr, mc_dst_addr);
- ecm_ip_addr_to_string(mc_dst_addr_str, ecm_multicast_dst_addr);
- ECM_NIN6_ADDR_TO_IP_ADDR(ecm_src_addr, src_addr);
- ecm_ip_addr_to_string(src_addr_str, ecm_src_addr);
-
- /*
- * Find the route entry
- */
- rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
- if (!rt6i) {
- DEBUG_TRACE("IPv6 Route lookup failure for destination IPv6 address %s\n", dst_addr_str);
- return;
- // GGG TODO Flatten
- } else {
- /*
- * Find the neighbor entry
- */
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
- neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
-#else
- neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
-#endif
- if (neigh == NULL) {
- DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address %s\n", dst_addr_str);
- return;
- } else {
- /*
- * Issue a Neighbour soliciation request
- */
- DEBUG_TRACE("Issue Neighbour solicitation request\n");
- ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
- neigh_release(neigh);
- }
- }
-}
-
-/*
- * ecm_front_end_ipv6_interface_heirarchy_construct()
- * Construct an interface heirarchy.
- *
- * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
- * This is the heirarchy of interfaces a packet would transit to emit from the device.
- *
- * We will use the given src/dest devices when is_routed is false.
- * When is_routed is true we will try routing tables first, failing back to any given.
- *
- * For example, with this network arrangement:
- *
- * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
- *
- * Given the IP address 10.22.33.11 this will create an interface heirarchy (in interracfes[]) of:
- * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
- * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
- * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
- * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
- * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
- * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
- *
- * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
- * they will be created and added automatically to the database.
- *
- * GGG TODO Remove this in favour of the ecm_interface version - understand any refactoring needs first.
- */
-int32_t ecm_front_end_ipv6_interface_heirarchy_construct(struct ecm_db_iface_instance *interfaces[], ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, int packet_protocol,
- struct net_device *given_dest_dev, bool is_routed, struct net_device *given_src_dev, uint8_t *dest_node_addr, uint8_t *src_node_addr)
-{
- int protocol;
- ip_addr_t src_addr;
- ip_addr_t dest_addr;
- struct net_device *dest_dev;
- char *dest_dev_name;
- int32_t dest_dev_type;
- struct net_device *src_dev;
- char *src_dev_name;
- int32_t src_dev_type;
- int32_t current_interface_index;
- bool from_local_addr;
-
- /*
- * Get a big endian of the IPv6 address we have been given as our starting point.
- */
- protocol = packet_protocol;
- ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
- ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
- DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_OCTAL_FMT " to dest_addr: " ECM_IP_ADDR_OCTAL_FMT ", protocol: %d\n",
- ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol);
-
- /*
- * Get device to reach the given destination address.
- * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_dest_dev.
- * If the heirarchy is NOT for a routed connection we try the given_dest_dev first, followed by routed lookup.
- */
- from_local_addr = false;
- if (is_routed) {
- dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
- if (!dest_dev && given_dest_dev) {
- /*
- * Fall back to any given
- */
- dest_dev = given_dest_dev;
- dev_hold(dest_dev);
- }
- } else if (given_dest_dev) {
- dest_dev = given_dest_dev;
- dev_hold(dest_dev);
- } else {
- /*
- * Fall back to routed look up
- */
- dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
- }
-
- /*
- * GGG ALERT: If the address is a local address and protocol is an IP tunnel
- * then this connection is a tunnel endpoint made to this device.
- * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
- * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
- * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
- * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
- */
- if (dest_dev && from_local_addr && (protocol == IPPROTO_IPIP)) {
- dev_put(dest_dev);
- dest_dev = given_dest_dev;
- if (dest_dev) {
- dev_hold(dest_dev);
- DEBUG_TRACE("HACK: IPIP tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
- }
- }
- if (!dest_dev) {
- DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
- dest_dev_name = dest_dev->name;
- dest_dev_type = dest_dev->type;
-
- /*
- * Get device to reach the given source address.
- * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_src_dev.
- * If the heirarchy is NOT for a routed connection we try the given_src_dev first, followed by routed lookup.
- */
- from_local_addr = false;
- if (is_routed) {
- src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
- if (!src_dev && given_src_dev) {
- /*
- * Fall back to any given
- */
- src_dev = given_src_dev;
- dev_hold(src_dev);
- }
- } else if (given_src_dev) {
- src_dev = given_src_dev;
- dev_hold(src_dev);
- } else {
- /*
- * Fall back to routed look up
- */
- src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
- }
-
- /*
- * GGG ALERT: If the address is a local address and protocol is an IP tunnel
- * then this connection is a tunnel endpoint made to this device.
- * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
- * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
- * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
- * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
- */
- if (src_dev && from_local_addr && (protocol == IPPROTO_IPIP)) {
- dev_put(src_dev);
- src_dev = given_src_dev;
- if (src_dev) {
- dev_hold(src_dev);
- DEBUG_TRACE("HACK: IPIP tunnel packet with src_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(src_addr), src_dev, src_dev->name);
- }
- }
- if (!src_dev) {
- DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
- dev_put(dest_dev);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
- src_dev_name = src_dev->name;
- src_dev_type = src_dev->type;
-
- /*
- * Check if source and dest dev are same.
- * For the forwarded flows which involve tunnels this will happen when called from input hook.
- */
- if (src_dev == dest_dev) {
- DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
- if (protocol == IPPROTO_IPIP) {
- /*
- * This happens from the input hook
- * We do not want to create a connection entry for this
- * GGG TODO YES WE DO.
- * GGG TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
- * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
- * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
- * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
- * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
- * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
- * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
- */
- dev_put(src_dev);
- dev_put(dest_dev);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
- }
-
- /*
- * Iterate until we are done or get to the max number of interfaces we can record.
- * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
- * because we add from the end first_interface grows downwards.
- */
- current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
- while (current_interface_index > 0) {
- struct ecm_db_iface_instance *ii;
- struct net_device *next_dev;
-
- /*
- * Get the ecm db interface instance for the device at hand
- */
- ii = ecm_interface_establish_and_ref(dest_dev);
-
- /*
- * If the interface could not be established then we abort
- */
- if (!ii) {
- DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
- dev_put(src_dev);
- dev_put(dest_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
-
- /*
- * Record the interface instance into the interfaces[]
- */
- current_interface_index--;
- interfaces[current_interface_index] = ii;
-
- /*
- * Now we have to figure out what the next device will be (in the transmission path) the skb
- * will use to emit to the destination address.
- */
- do {
-#ifdef ECM_INTERFACE_PPP_ENABLE
- int channel_count;
- struct ppp_channel *ppp_chan[1];
- int channel_protocol;
- struct pppoe_opt addressing;
-#endif
-
- DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
- next_dev = NULL;
-
- if (dest_dev_type == ARPHRD_ETHER) {
- /*
- * Ethernet - but what sub type?
- */
-
-#ifdef ECM_INTERFACE_VLAN_ENABLE
- /*
- * VLAN?
- */
- if (is_vlan_dev(dest_dev)) {
- /*
- * VLAN master
- * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
- */
- next_dev = vlan_dev_priv(dest_dev)->real_dev;
- dev_hold(next_dev);
- DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
- dest_dev, next_dev, next_dev->name);
- break;
- }
-#endif
-
- /*
- * BRIDGE?
- */
- if (ecm_front_end_is_bridge_device(dest_dev)) {
- /*
- * Bridge
- * Figure out which port device the skb will go to using the dest_addr.
- */
- bool on_link;
- ip_addr_t gw_addr;
- uint8_t mac_addr[ETH_ALEN];
- if (!ecm_interface_mac_addr_get(dest_addr, mac_addr, &on_link, gw_addr)) {
- /*
- * Possible ARP does not know the address yet
- */
- DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
- ecm_front_end_ipv6_send_neighbour_solicitation(dest_dev, dest_addr);
- dev_put(src_dev);
- dev_put(dest_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
- next_dev = br_port_dev_get(dest_dev, mac_addr);
- if (!next_dev) {
- DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
- dev_put(src_dev);
- dev_put(dest_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
- DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
- break;
- }
-#ifdef ECM_INTERFACE_BOND_ENABLE
- /*
- * LAG?
- */
- if (ecm_front_end_is_lag_master(dest_dev)) {
- /*
- * Link aggregation
- * Figure out which slave device of the link aggregation will be used to reach the destination.
- */
- bool dest_on_link = false;
- ip_addr_t dest_gw_addr = ECM_IP_ADDR_NULL;
- uint8_t src_mac_addr[ETH_ALEN];
- uint8_t dest_mac_addr[ETH_ALEN];
- struct net_device *master_dev = NULL;
-
- memset(src_mac_addr, 0, ETH_ALEN);
- memset(dest_mac_addr, 0, ETH_ALEN);
-
- if (!is_routed) {
- memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
- memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
- } else {
- struct net_device *dest_dev_master;
- /*
- * Use appropriate source MAC address for routed packets
- */
- dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
- if (dest_dev_master) {
- memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
- } else {
- memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
- }
-
- if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr, &dest_on_link, dest_gw_addr)) {
- /*
- * Possible ARP does not know the address yet
- */
- DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
-
- /*
- * find proper interfce from which to issue neighbour solicitation
- */
- if (dest_dev_master) {
- master_dev = dest_dev_master;
- } else {
- master_dev = dest_dev;
- }
-
- dev_hold(master_dev);
-
- if (dest_dev_master) {
- dev_put(dest_dev_master);
- }
-
- ecm_front_end_ipv6_send_neighbour_solicitation(master_dev, dest_addr);
- dev_put(src_dev);
- dev_put(dest_dev);
- dev_put(master_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
-
- if (dest_dev_master) {
- dev_put(dest_dev_master);
- }
- }
-
- next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr, src_addr, dest_addr, htons((uint16_t)ETH_P_IPV6), dest_dev);
- if (next_dev && netif_carrier_ok(next_dev)) {
- dev_hold(next_dev);
- } else {
- DEBUG_WARN("Unable to obtain LAG output slave device\n");
- dev_put(src_dev);
- dev_put(dest_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
- }
-
- DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
-
- break;
- }
-#endif
-
- /*
- * ETHERNET!
- * Just plain ethernet it seems.
- */
- DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
- break;
- }
-
- /*
- * LOOPBACK?
- */
- if (dest_dev_type == ARPHRD_LOOPBACK) {
- DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
- break;
- }
-
- /*
- * IPSEC?
- */
- if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
- DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
- // GGG TODO Figure out the next device the tunnel is using...
- break;
- }
-
- /*
- * SIT (6-in-4)?
- */
- if (dest_dev_type == ARPHRD_SIT) {
- DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
- // GGG TODO Figure out the next device the tunnel is using...
- break;
- }
-
- /*
- * IPIP6 Tunnel?
- */
- if (dest_dev_type == ARPHRD_TUNNEL6) {
- DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
- // GGG TODO Figure out the next device the tunnel is using...
- break;
- }
-
- /*
- * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
- */
- if (dest_dev_type != ARPHRD_PPP) {
- DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
- break;
- }
-
-#ifndef ECM_INTERFACE_PPP_ENABLE
- DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
-#else
- /*
- * PPP - but what is the channel type?
- * First: If this is multi-link then we do not support it
- */
- if (ppp_is_multilink(dest_dev) > 0) {
- DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
- break;
- }
-
- DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
-
- /*
- * Get the PPP channel and then enquire what kind of channel it is
- * NOTE: Not multilink so only one channel to get.
- */
- channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
- if (channel_count != 1) {
- DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
- dest_dev, channel_count);
- break;
- }
-
- /*
- * Get channel protocol type
- * NOTE: Not all PPP channels support channel specific methods.
- */
- channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
- if (channel_protocol != PX_PROTO_OE) {
- DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
- dest_dev, channel_protocol);
-
- /*
- * Release the channel
- */
- ppp_release_channels(ppp_chan, 1);
-
- break;
- }
-
- /*
- * PPPoE channel
- */
- DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
-
- /*
- * Get PPPoE session information and the underlying device it is using.
- */
- pppoe_channel_addressing_get(ppp_chan[0], &addressing);
-
- /*
- * Copy the dev hold into this, we will release the hold later
- */
- next_dev = addressing.dev;
-
- DEBUG_TRACE("Net device: %p, next device: %p (%s)\n", dest_dev, next_dev, next_dev->name);
-
- /*
- * Release the channel. Note that next_dev is still (correctly) held.
- */
- ppp_release_channels(ppp_chan, 1);
-#endif
- } while (false);
-
- /*
- * No longer need dest_dev as it may become next_dev
- */
- dev_put(dest_dev);
-
- /*
- * Check out the next_dev, if any
- */
- if (!next_dev) {
- int32_t i __attribute__((unused));
- DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
-#if DEBUG_LEVEL > 1
- for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
- DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
- i, interfaces[i], ecm_db_connection_iface_type_get(interfaces[i]),
- ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(interfaces[i])));
- }
-#endif
- /*
- * Release src_dev now
- */
- dev_put(src_dev);
- return current_interface_index;
- }
-
- /*
- * dest_dev becomes next_dev
- */
- dest_dev = next_dev;
- dest_dev_name = dest_dev->name;
- dest_dev_type = dest_dev->type;
- }
-
- DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
- DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
- dev_put(src_dev);
- dev_put(dest_dev);
-
- /*
- * Release the interfaces heirarchy we constructed to this point.
- */
- ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
- return ECM_DB_IFACE_HEIRARCHY_MAX;
-}
-
-/*
* ecm_front_end_ipv6_node_establish_and_ref()
* Returns a reference to a node, possibly creating one if necessary.
*
@@ -895,10 +288,10 @@
struct net_device *master;
master = ecm_interface_get_and_hold_dev_master(dev);
DEBUG_ASSERT(master, "Expected a master\n");
- ecm_front_end_ipv6_send_neighbour_solicitation(master, addr);
+ ecm_interface_send_neighbour_solicitation(master, addr);
dev_put(master);
} else {
- ecm_front_end_ipv6_send_neighbour_solicitation(dev, addr);
+ ecm_interface_send_neighbour_solicitation(dev, addr);
}
return NULL;
}
@@ -5874,7 +5267,7 @@
ecm_db_connection_to_node_address_get(ci, dest_node_addr);
DEBUG_TRACE("%p: Update the 'from' interface heirarchy list\n", ci);
- from_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 6, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
goto ecm_ipv6_retry_regen;
}
@@ -5883,7 +5276,7 @@
ecm_db_connection_interfaces_deref(from_list, from_list_first);
DEBUG_TRACE("%p: Update the 'to' interface heirarchy list\n", ci);
- to_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 6, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
goto ecm_ipv6_retry_regen;
}
@@ -6112,7 +5505,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, IPPROTO_TCP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 6, IPPROTO_TCP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
@@ -6139,7 +5532,7 @@
}
DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
- to_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, IPPROTO_TCP, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 6, IPPROTO_TCP, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_mi);
ecm_db_node_deref(src_ni);
@@ -6639,7 +6032,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, IPPROTO_UDP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 6, IPPROTO_UDP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
@@ -6666,7 +6059,7 @@
}
DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
- to_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, IPPROTO_UDP, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 6, IPPROTO_UDP, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_mi);
ecm_db_node_deref(src_ni);
@@ -7122,7 +6515,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 6, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
@@ -7149,7 +6542,7 @@
}
DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
- to_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 6, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_mi);
ecm_db_node_deref(src_ni);
@@ -8824,7 +8217,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_front_end_ipv6_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, IPPROTO_UDP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 6, IPPROTO_UDP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c
index 24b58ff..4ee3d8e 100644
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b/frontends/nss/ecm_nss_ipv4.c
@@ -237,34 +237,15 @@
case ECM_DB_IFACE_TYPE_BRIDGE:
case ECM_DB_IFACE_TYPE_IPSEC_TUNNEL:
if (!ecm_interface_mac_addr_get(addr, node_addr, &on_link, gw_addr)) {
- __be32 ipv4_addr;
- __be32 src_ip;
DEBUG_TRACE("failed to obtain node address for host " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(addr));
- /*
- * Issue an ARP request for it, select the src_ip from which to issue the request.
- */
- ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
- src_ip = inet_select_addr(dev, ipv4_addr, RT_SCOPE_LINK);
- if (!src_ip) {
- DEBUG_TRACE("failed to lookup IP for %pI4\n", &ipv4_addr);
- return NULL;
- }
-
- /*
- * If we have a GW for this address, then we have to send ARP request to the GW
- */
- if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
- ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
- }
-
- DEBUG_TRACE("Send ARP for %pI4 using src_ip as %pI4\n", &ipv4_addr, &src_ip);
- arp_send(ARPOP_REQUEST, ETH_P_ARP, ipv4_addr, dev, src_ip, NULL, NULL, NULL);
+ ecm_interface_send_arp_request(dev, addr, on_link, gw_addr);
/*
* Unable to get node address at this time.
*/
return NULL;
}
+
if (is_multicast_ether_addr(node_addr)) {
DEBUG_TRACE("multicast node address for host " ECM_IP_ADDR_DOT_FMT ", node_addr: %pM\n", ECM_IP_ADDR_TO_DOT(addr), node_addr);
return NULL;
@@ -732,7 +713,7 @@
DEBUG_TRACE("%p: Update the 'from' interface heirarchy list\n", ci);
- from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 4, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
goto ecm_ipv4_retry_regen;
}
@@ -741,7 +722,7 @@
ecm_db_connection_interfaces_deref(from_list, from_list_first);
DEBUG_TRACE("%p: Update the 'from NAT' interface heirarchy list\n", ci);
- from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, protocol, in_dev_nat, is_routed, in_dev_nat, src_node_addr_nat, dest_node_addr_nat);
+ from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, 4, protocol, in_dev_nat, is_routed, in_dev_nat, src_node_addr_nat, dest_node_addr_nat);
if (from_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
goto ecm_ipv4_retry_regen;
}
@@ -750,7 +731,7 @@
ecm_db_connection_interfaces_deref(from_nat_list, from_nat_list_first);
DEBUG_TRACE("%p: Update the 'to' interface heirarchy list\n", ci);
- to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 4, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
goto ecm_ipv4_retry_regen;
}
@@ -759,7 +740,7 @@
ecm_db_connection_interfaces_deref(to_list, to_list_first);
DEBUG_TRACE("%p: Update the 'to NAT' interface heirarchy list\n", ci);
- to_nat_list_first = ecm_interface_heirarchy_construct(to_nat_list, ip_src_addr, ip_dest_addr_nat, protocol, out_dev_nat, is_routed, in_dev, dest_node_addr_nat, src_node_addr_nat);
+ to_nat_list_first = ecm_interface_heirarchy_construct(to_nat_list, ip_src_addr, ip_dest_addr_nat, 4, protocol, out_dev_nat, is_routed, in_dev, dest_node_addr_nat, src_node_addr_nat);
if (to_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
goto ecm_ipv4_retry_regen;
}
diff --git a/frontends/nss/ecm_nss_multicast_ipv4.c b/frontends/nss/ecm_nss_multicast_ipv4.c
index afdace0..60d0127 100644
--- a/frontends/nss/ecm_nss_multicast_ipv4.c
+++ b/frontends/nss/ecm_nss_multicast_ipv4.c
@@ -2161,7 +2161,7 @@
* For this we also need the interface lists which we also set upon the new connection while we are at it.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 4, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
@@ -2264,7 +2264,7 @@
}
DEBUG_TRACE("%p: Create the 'from NAT' interface heirarchy list\n", nci);
- from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, protocol, in_dev_nat, is_routed, in_dev_nat, src_node_addr, dest_node_addr);
+ from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, 4, protocol, in_dev_nat, is_routed, in_dev_nat, src_node_addr, dest_node_addr);
if (from_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
diff --git a/frontends/nss/ecm_nss_non_ported_ipv4.c b/frontends/nss/ecm_nss_non_ported_ipv4.c
index f6b0427..eacd916 100644
--- a/frontends/nss/ecm_nss_non_ported_ipv4.c
+++ b/frontends/nss/ecm_nss_non_ported_ipv4.c
@@ -1822,7 +1822,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 4, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
@@ -1849,7 +1849,7 @@
}
DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
- to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 4, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_mi);
ecm_db_node_deref(src_ni);
@@ -1893,9 +1893,9 @@
*/
DEBUG_TRACE("%p: Create the 'from NAT' interface heirarchy list\n", nci);
if ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)) {
- from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, protocol, in_dev, is_routed, in_dev, src_node_addr_nat, dest_node_addr_nat);
+ from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, 4, protocol, in_dev, is_routed, in_dev, src_node_addr_nat, dest_node_addr_nat);
} else {
- from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, protocol, in_dev_nat, is_routed, in_dev, src_node_addr_nat, dest_node_addr_nat);
+ from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, 4, protocol, in_dev_nat, is_routed, in_dev, src_node_addr_nat, dest_node_addr_nat);
}
if (from_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
@@ -1935,7 +1935,7 @@
}
DEBUG_TRACE("%p: Create the 'to NAT' interface heirarchy list\n", nci);
- to_nat_list_first = ecm_interface_heirarchy_construct(to_nat_list, ip_src_addr, ip_dest_addr_nat, protocol, out_dev_nat, is_routed, in_dev, dest_node_addr_nat, src_node_addr_nat);
+ to_nat_list_first = ecm_interface_heirarchy_construct(to_nat_list, ip_src_addr, ip_dest_addr_nat, 4, protocol, out_dev_nat, is_routed, in_dev, dest_node_addr_nat, src_node_addr_nat);
if (to_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_nat_mi);
ecm_db_node_deref(src_nat_ni);
diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c
index 0b19772..13dc1f1 100644
--- a/frontends/nss/ecm_nss_ported_ipv4.c
+++ b/frontends/nss/ecm_nss_ported_ipv4.c
@@ -1964,7 +1964,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
- from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
+ from_list_first = ecm_interface_heirarchy_construct(from_list, ip_dest_addr, ip_src_addr, 4, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr);
if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
@@ -1991,7 +1991,7 @@
}
DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
- to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
+ to_list_first = ecm_interface_heirarchy_construct(to_list, ip_src_addr, ip_dest_addr, 4, protocol, out_dev, is_routed, in_dev, dest_node_addr, src_node_addr);
if (to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_mi);
ecm_db_node_deref(src_ni);
@@ -2030,7 +2030,7 @@
* GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
*/
DEBUG_TRACE("%p: Create the 'from NAT' interface heirarchy list\n", nci);
- from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, protocol, in_dev_nat, is_routed, in_dev_nat, src_node_addr_nat, dest_node_addr_nat);
+ from_nat_list_first = ecm_interface_heirarchy_construct(from_nat_list, ip_dest_addr, ip_src_addr_nat, 4, protocol, in_dev_nat, is_routed, in_dev_nat, src_node_addr_nat, dest_node_addr_nat);
if (from_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(dest_mi);
ecm_db_node_deref(dest_ni);
@@ -2068,7 +2068,7 @@
}
DEBUG_TRACE("%p: Create the 'to NAT' interface heirarchy list\n", nci);
- to_nat_list_first = ecm_interface_heirarchy_construct(to_nat_list, ip_src_addr, ip_dest_addr_nat, protocol, out_dev_nat, is_routed, in_dev, dest_node_addr_nat, src_node_addr_nat);
+ to_nat_list_first = ecm_interface_heirarchy_construct(to_nat_list, ip_src_addr, ip_dest_addr_nat, 4, protocol, out_dev_nat, is_routed, in_dev, dest_node_addr_nat, src_node_addr_nat);
if (to_nat_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
ecm_db_mapping_deref(src_nat_mi);
ecm_db_node_deref(src_nat_ni);