diff --git a/src/host.c b/src/host.c index 59b71a551589697b493b5201bedc44343e868c4e..fca12b169a8a21bebb123d0c6a398324140f2909 100644 --- a/src/host.c +++ b/src/host.c @@ -1405,7 +1405,7 @@ void host_remove_aged_node(struct topologyd_private *priv) hwaddr_ntoa(p->hwaddr, mac_str); config_del_section("hosts", "host", mac_str, priv->host_global_cfg.persistent); dbg("Ageing timeout delecting mac node = ["MACFMT"]\n", MAC2STR(p->hwaddr)); - host_node_del(priv->host.node_htable, p->hwaddr); + host_node_del(priv->host.node_htable, p->hwaddr, priv); priv->host.num_nodes--; } } diff --git a/src/host.h b/src/host.h index e85ff1b8454a2bb07a16d50711b78f49dee9dd35..88e21e00f59007765357f960850cffd10b11ea4a 100644 --- a/src/host.h +++ b/src/host.h @@ -85,7 +85,6 @@ struct host_node { unsigned long long rx_packets; unsigned long long tx_packets; } stats; - struct hlist_head nf_tc; //char addrsrc[8]; enum address_type addrsrc; unsigned int leasetmrmn; diff --git a/src/host_nodes.c b/src/host_nodes.c index e2765f65bdbb3f05a88d4ae20788d06dd374ddfd..05274f70dc5f3995b63182155e595028245f0913 100644 --- a/src/host_nodes.c +++ b/src/host_nodes.c @@ -25,11 +25,16 @@ #include "host_nodes.h" #include <libnetfilter_conntrack/libnetfilter_conntrack.h> - struct host_nf_tc { - struct nf_conntrack *tc; struct hlist_node hlist; + unsigned int id; + unsigned long long start_timestamp; + unsigned long long rx_bytes; + unsigned long long tx_bytes; + unsigned long long rx_packets; + unsigned long long tx_packets; int in_use; + struct host_node *host; }; void host_node_destroy(struct host_node *n) @@ -69,7 +74,7 @@ struct host_node *host_node_lookup(struct hlist_head *table, uint8_t *hwaddr) return NULL; } -int host_node_del(struct hlist_head *table, uint8_t *hwaddr) +int host_node_del(struct hlist_head *table, uint8_t *hwaddr, struct topologyd_private *priv) { int hidx = node_hash(hwaddr); struct host_node *n; @@ -81,7 +86,7 @@ int host_node_del(struct hlist_head *table, uint8_t *hwaddr) hlist_del(&n->hlist, &table[hidx]); dbg("Node " MACFMT " removed from topology\n", MAC2STR(n->hwaddr)); - host_node_nf_list_clean(n); + host_node_ct_list_clean(n, priv); host_node_destroy(n); return 0; @@ -130,120 +135,119 @@ void host_node_print_all(struct hlist_head *table) } } -void host_node_nf_node_destroy(struct host_nf_tc *nf_tc) +void host_node_ct_node_destroy(struct host_nf_tc *nf_tc) { - nfct_destroy(nf_tc->tc); free(nf_tc); } -void host_node_nfct_copy(struct nf_conntrack *tc, struct nf_conntrack *ct) +void host_node_nfct_copy(struct host_nf_tc *host_ct, struct nf_conntrack *ct) { - nfct_copy(tc, ct, NFCT_CP_OVERRIDE); + host_ct->id = nfct_get_attr_u32(ct, ATTR_ID); + host_ct->start_timestamp = nfct_get_attr_u64(ct, ATTR_TIMESTAMP_START); } -struct host_nf_tc *host_node_nf_tc_create(struct nf_conntrack *ct) +struct host_nf_tc *host_node_ct_node_create(struct nf_conntrack *ct) { struct host_nf_tc *n = NULL; - struct nf_conntrack *tc = NULL; n = calloc(1, sizeof(struct host_nf_tc)); if (!n) { warn("OOM: Node alloc failed!\n"); return NULL; } - tc = nfct_new(); - if (!tc) { - free(n); - warn("OOM: Node alloc failed!\n"); - return NULL; - } - n->tc = tc; - host_node_nfct_copy(n->tc, ct); + host_node_nfct_copy(n, ct); return n; } -struct host_nf_tc *host_node_nf_node_lookup(struct hlist_head *table, struct nf_conntrack *ct) +struct host_nf_tc *host_node_ct_node_lookup(struct topologyd_private *priv, struct nf_conntrack *ct) { struct host_nf_tc *n = NULL; + unsigned int id; + unsigned long long start_timestamp; - hlist_for_each_entry(n, table, hlist) { - if (nfct_cmp(n->tc, ct, NFCT_CMP_ORIG)) + id = nfct_get_attr_u32(ct, ATTR_ID); + start_timestamp = nfct_get_attr_u64(ct, ATTR_TIMESTAMP_START); + hlist_for_each_entry(n, &priv->host.ct_node_htable[ct_node_hash(id)], hlist) { + if (id == n->id && start_timestamp == n->start_timestamp) return n; } return NULL; } -void host_node_nf_list_clean(struct host_node *host) +void host_node_ct_list_clean(const struct host_node *host, struct topologyd_private *priv) { struct host_nf_tc *expired_entry = NULL; - struct hlist_node *p, *n; + struct host_nf_tc *n = NULL; + int i; - hlist_for_each_safe(p, n, &host->nf_tc){ - expired_entry = container_of(p, struct host_nf_tc, hlist); - hlist_del(&expired_entry->hlist, &host->nf_tc); - host_node_nf_node_destroy(expired_entry); + for (i = 0; i < CT_NODE_HTABLE_SIZE ; i++) { + if (hlist_empty(&priv->host.ct_node_htable[i])) + continue; + + hlist_for_each_entry(n, &priv->host.ct_node_htable[i], hlist) { + if(expired_entry) { + hlist_del(&expired_entry->hlist, &priv->host.ct_node_htable[i]); + host_node_ct_node_destroy(expired_entry); + expired_entry = NULL; + } + if (n->host && n->host == host) + expired_entry = n; + } + if(expired_entry) { + hlist_del(&expired_entry->hlist, &priv->host.ct_node_htable[i]); + host_node_ct_node_destroy(expired_entry); + expired_entry = NULL; + } } } -struct host_nf_tc *host_node_nf_node_add(struct hlist_head *table, struct nf_conntrack *ct) +struct host_nf_tc *host_node_ct_node_add(struct nf_conntrack *ct, struct topologyd_private *priv, struct host_node *host) { struct host_nf_tc *n = NULL; - n = host_node_nf_tc_create(ct); + n = host_node_ct_node_create(ct); if (n) { - hlist_add_head(&n->hlist, table); + hlist_add_head(&n->hlist, &priv->host.ct_node_htable[ct_node_hash(n->id)]); n->in_use = 1; + n->host = host; } return n; } -int host_node_update_stats(struct nf_conntrack *ct, struct host_node *host) +int host_node_update_stats(struct nf_conntrack *ct, struct host_nf_tc *ct_node) { struct nfct_attr_grp_ctrs grp_ctrs_tx; struct nfct_attr_grp_ctrs grp_ctrs_rx; - struct nfct_attr_grp_ctrs grp_ctrs_tx_prev; - struct nfct_attr_grp_ctrs grp_ctrs_rx_prev; - struct host_nf_tc *n; - memset(&grp_ctrs_tx_prev, 0, sizeof(struct nfct_attr_grp_ctrs)); - memset(&grp_ctrs_rx_prev, 0, sizeof(struct nfct_attr_grp_ctrs)); memset(&grp_ctrs_tx, 0, sizeof(struct nfct_attr_grp_ctrs)); memset(&grp_ctrs_rx, 0, sizeof(struct nfct_attr_grp_ctrs)); nfct_get_attr_grp(ct, ATTR_GRP_ORIG_COUNTERS, &grp_ctrs_tx); nfct_get_attr_grp(ct, ATTR_GRP_REPL_COUNTERS, &grp_ctrs_rx); - n = host_node_nf_node_lookup(&host->nf_tc, ct); - if (n) { - nfct_get_attr_grp(n->tc, ATTR_GRP_ORIG_COUNTERS, &grp_ctrs_tx_prev); - nfct_get_attr_grp(n->tc, ATTR_GRP_REPL_COUNTERS, &grp_ctrs_rx_prev); - - if (grp_ctrs_tx.packets >= grp_ctrs_tx_prev.packets || grp_ctrs_rx.packets >= grp_ctrs_rx_prev.packets) { - host->stats.tx_packets += (grp_ctrs_tx.packets - grp_ctrs_tx_prev.packets); - host->stats.tx_bytes += (grp_ctrs_tx.bytes - grp_ctrs_tx_prev.bytes); - host->stats.rx_packets += (grp_ctrs_rx.packets - grp_ctrs_rx_prev.packets); - host->stats.rx_bytes += (grp_ctrs_rx.bytes - grp_ctrs_rx_prev.bytes); + if (ct_node) { + + if (grp_ctrs_tx.packets >= ct_node->tx_packets || grp_ctrs_rx.packets >= ct_node->rx_packets) { + ct_node->host->stats.tx_packets += (grp_ctrs_tx.packets - ct_node->tx_packets); + ct_node->host->stats.tx_bytes += (grp_ctrs_tx.bytes - ct_node->tx_bytes); + ct_node->host->stats.rx_packets += (grp_ctrs_rx.packets - ct_node->rx_packets); + ct_node->host->stats.rx_bytes += (grp_ctrs_rx.bytes - ct_node->rx_bytes); } else { - host->stats.tx_packets += grp_ctrs_tx.packets; - host->stats.tx_bytes += grp_ctrs_tx.bytes; - host->stats.rx_packets += grp_ctrs_rx.packets; - host->stats.rx_bytes += grp_ctrs_rx.bytes; - } - host_node_nfct_copy(n->tc, ct); - n->in_use = 1; - } - else { - if (host_node_nf_node_add(&host->nf_tc, ct)) { - host->stats.tx_packets += grp_ctrs_tx.packets; - host->stats.tx_bytes += grp_ctrs_tx.bytes; - host->stats.rx_packets += grp_ctrs_rx.packets; - host->stats.rx_bytes += grp_ctrs_rx.bytes; + ct_node->host->stats.tx_packets += grp_ctrs_tx.packets; + ct_node->host->stats.tx_bytes += grp_ctrs_tx.bytes; + ct_node->host->stats.rx_packets += grp_ctrs_rx.packets; + ct_node->host->stats.rx_bytes += grp_ctrs_rx.bytes; } + ct_node->in_use = 1; + ct_node->tx_packets = grp_ctrs_tx.packets; + ct_node->rx_packets = grp_ctrs_rx.packets; + ct_node->tx_bytes = grp_ctrs_tx.bytes; + ct_node->rx_bytes = grp_ctrs_rx.bytes; } return NFCT_CB_CONTINUE; @@ -262,6 +266,7 @@ int host_node_ipv6_stats_received(enum nf_conntrack_msg_type type, char ipv6_addr[sizeof(int)*4]; char ipv6_dst_addr[sizeof(int)*4]; int addr_part; + struct host_nf_tc *ct_node = NULL; nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, &grp_ipv6); addr_part = (grp_ipv6.src[0]); @@ -288,6 +293,10 @@ int host_node_ipv6_stats_received(enum nf_conntrack_msg_type type, if (host_is_device_address(priv, ipv6_dst_addr, AF_INET6)) return NFCT_CB_CONTINUE; + ct_node = host_node_ct_node_lookup(priv, ct); + if (ct_node) + return host_node_update_stats(ct, ct_node); + for (i = 0; i < NODE_HTABLE_SIZE ; i++) { if ((hlist_empty(&priv->host.node_htable[i]))) continue; @@ -303,7 +312,8 @@ int host_node_ipv6_stats_received(enum nf_conntrack_msg_type type, inet_pton(AF_INET6, host->ipv6addr[count], &sa6.sin6_addr); if (!memcmp(ipv6_addr, sa6.sin6_addr.s6_addr, sizeof(int)*4)) { - return host_node_update_stats(ct, host); + ct_node = host_node_ct_node_add(ct, priv, host); + return host_node_update_stats(ct, ct_node); } } } @@ -323,6 +333,7 @@ int host_node_stats_received(enum nf_conntrack_msg_type type, struct sockaddr_in sa; int count; struct in_addr dest_addr; + struct host_nf_tc *ct_node = NULL; ret_val=nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV4, &grp_ipv4); if (ret_val || priv == NULL) @@ -332,6 +343,10 @@ int host_node_stats_received(enum nf_conntrack_msg_type type, if (host_is_device_address(priv, inet_ntoa(dest_addr), AF_INET)) return NFCT_CB_CONTINUE; + ct_node = host_node_ct_node_lookup(priv, ct); + if (ct_node) + return host_node_update_stats(ct, ct_node); + for (i = 0; i < NODE_HTABLE_SIZE ; i++) { if ((hlist_empty(&priv->host.node_htable[i]))) continue; @@ -348,7 +363,8 @@ int host_node_stats_received(enum nf_conntrack_msg_type type, inet_pton(AF_INET, host->ipv4addr_list[count], &(sa.sin_addr)); if (grp_ipv4.src == sa.sin_addr.s_addr) { - return host_node_update_stats(ct, host); + ct_node = host_node_ct_node_add(ct, priv, host); + return host_node_update_stats(ct, ct_node); } } } @@ -377,6 +393,7 @@ void host_node_nfct_query(struct nfct_handle *cth, int family, struct topologyd_ filter_dump = nfct_filter_dump_create(); if (filter_dump == NULL) { + nfct_destroy(ct); err("%s Failed to allocate filter_dump", __FUNCTION__); return; } @@ -396,30 +413,23 @@ void host_node_clean_nf_tc(struct topologyd_private *priv) int i; struct host_nf_tc *expired_entry = NULL; struct host_nf_tc *n = NULL; - struct host_node *host = NULL; - for (i = 0; i < NODE_HTABLE_SIZE ; i++) { - if ((hlist_empty(&priv->host.node_htable[i]))) + for (i = 0; i < CT_NODE_HTABLE_SIZE ; i++) { + if ((hlist_empty(&priv->host.ct_node_htable[i]))) continue; - - hlist_for_each_entry(host, &priv->host.node_htable[i], hlist) { - if (hwaddr_is_zero(host->hwaddr) || (host->is_copy == 1) || - (host->intf_type != HOST_TYPE_ETHER && host->intf_type !=HOST_TYPE_WIFI)) - continue; - hlist_for_each_entry(n, &host->nf_tc, hlist) { - if(expired_entry) { - hlist_del(&expired_entry->hlist, &host->nf_tc); - host_node_nf_node_destroy(expired_entry); - expired_entry = NULL; - } - if (!n->in_use) - expired_entry = n; + hlist_for_each_entry(n, &priv->host.ct_node_htable[i], hlist) { + if(expired_entry) { + hlist_del(&expired_entry->hlist, &priv->host.ct_node_htable[i]); + host_node_ct_node_destroy(expired_entry); + expired_entry = NULL; + } + if (!n->in_use) + expired_entry = n; } if(expired_entry) { - hlist_del(&expired_entry->hlist, &host->nf_tc); - host_node_nf_node_destroy(expired_entry); + hlist_del(&expired_entry->hlist, &priv->host.ct_node_htable[i]); + host_node_ct_node_destroy(expired_entry); expired_entry = NULL; - } } } } @@ -428,21 +438,14 @@ int host_node_get_statistics(struct topologyd_private *priv) { struct nfct_handle *cth; struct host_nf_tc *n = NULL; - struct host_node *host = NULL; int i = 0; - for (i = 0; i < NODE_HTABLE_SIZE ; i++) { - if ((hlist_empty(&priv->host.node_htable[i]))) + for (i = 0; i < CT_NODE_HTABLE_SIZE ; i++) { + if ((hlist_empty(&priv->host.ct_node_htable[i]))) continue; - hlist_for_each_entry(host, &priv->host.node_htable[i], hlist) { - if (hwaddr_is_zero(host->hwaddr) || (host->is_copy == 1) || - (host->intf_type != HOST_TYPE_ETHER && host->intf_type !=HOST_TYPE_WIFI)) - continue; - - hlist_for_each_entry(n, &host->nf_tc, hlist) { - n->in_use = 0; - } + hlist_for_each_entry(n, &priv->host.ct_node_htable[i], hlist) { + n->in_use = 0; } } diff --git a/src/host_nodes.h b/src/host_nodes.h index 9df6d068326830a1ab4a344b685502ccf196a9c3..f1671a744176ef07c9470f7775563810adb8704a 100644 --- a/src/host_nodes.h +++ b/src/host_nodes.h @@ -6,9 +6,9 @@ struct host_node *host_node_create(uint8_t *hwaddr); void host_node_free(struct host_node *n); struct host_node *host_node_add(struct hlist_head *table, uint8_t *hwaddr); -int host_node_del(struct hlist_head *table, uint8_t *hwaddr); +int host_node_del(struct hlist_head *table, uint8_t *hwaddr, struct topologyd_private *priv); struct host_node *host_node_lookup(struct hlist_head *table, uint8_t *hwaddr); void host_node_print_all(struct hlist_head *table); -void host_node_nf_list_clean(struct host_node *host); +void host_node_ct_list_clean(const struct host_node *host, struct topologyd_private *priv); #endif /* HOST_NODES_H */ diff --git a/src/ieee1905/topologyd.h b/src/ieee1905/topologyd.h index c83840260eadd9b9d17aef1f2712f63d74875443..9c40d65a2710965a17d343ac704462344f5880e7 100644 --- a/src/ieee1905/topologyd.h +++ b/src/ieee1905/topologyd.h @@ -219,6 +219,8 @@ struct topology_changelog { #define NODE_HTABLE_SIZE 128 #define node_hash(n) \ ((n[0] ^ n[1] ^ n[2] ^ n[3] ^ n[4] ^ n[5]) % NODE_HTABLE_SIZE) +#define CT_NODE_HTABLE_SIZE 128 +#define ct_node_hash(n) (n % 128) struct topology { @@ -243,6 +245,7 @@ struct host_ntwk { void *priv; int32_t num_nodes; struct hlist_head node_htable[NODE_HTABLE_SIZE]; + struct hlist_head ct_node_htable[CT_NODE_HTABLE_SIZE]; }; struct topologyd_private {