+/* Hide unwanted ports depending on smart mode set by the user */
+static void
+lldpd_hide_all(struct lldpd *cfg)
+{
+ struct lldpd_hardware *hardware;
+
+ if (!cfg->g_smart)
+ return;
+ TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
+ if (cfg->g_smart & SMART_INCOMING_FILTER)
+ lldpd_hide_ports(cfg, hardware, SMART_INCOMING);
+ if (cfg->g_smart & SMART_OUTGOING_FILTER)
+ lldpd_hide_ports(cfg, hardware, SMART_OUTGOING);
+ }
+}
+
+static void
+lldpd_hide_ports(struct lldpd *cfg, struct lldpd_hardware *hardware, int mask) {
+ struct lldpd_port *port;
+ int protocols[LLDPD_MODE_MAX+1];
+ char buffer[256];
+ int i, j, k, found;
+ unsigned int min;
+
+ /* Compute the number of occurrences of each protocol */
+ for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
+ TAILQ_FOREACH(port, &hardware->h_rports, p_entries)
+ protocols[port->p_protocol]++;
+
+ /* Turn the protocols[] array into an array of
+ enabled/disabled protocols. 1 means enabled, 0
+ means disabled. */
+ min = (unsigned int)-1;
+ for (i = 0; i <= LLDPD_MODE_MAX; i++)
+ if (protocols[i] && (protocols[i] < min))
+ min = protocols[i];
+ found = 0;
+ for (i = 0; i <= LLDPD_MODE_MAX; i++)
+ if ((protocols[i] == min) && !found) {
+ /* If we need a tie breaker, we take
+ the first protocol only */
+ if (cfg->g_smart & mask &
+ (SMART_OUTGOING_ONE_PROTO | SMART_INCOMING_ONE_PROTO))
+ found = 1;
+ protocols[i] = 1;
+ } else protocols[i] = 0;
+
+ /* We set the p_hidden flag to 1 if the protocol is disabled */
+ TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
+ if (mask == SMART_OUTGOING)
+ port->p_hidden_out = protocols[port->p_protocol]?0:1;
+ else
+ port->p_hidden_in = protocols[port->p_protocol]?0:1;
+ }
+
+ /* If we want only one neighbor, we take the first one */
+ if (cfg->g_smart & mask &
+ (SMART_OUTGOING_ONE_NEIGH | SMART_INCOMING_ONE_NEIGH)) {
+ found = 0;
+ TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
+ if (mask == SMART_OUTGOING) {
+ if (found) port->p_hidden_out = 1;
+ if (!port->p_hidden_out)
+ found = 1;
+ }
+ if (mask == SMART_INCOMING) {
+ if (found) port->p_hidden_in = 1;
+ if (!port->p_hidden_in)
+ found = 1;
+ }
+ }
+ }
+
+ /* Print a debug message summarizing the operation */
+ for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
+ k = j = 0;
+ TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
+ if (!(((mask == SMART_OUTGOING) && port->p_hidden_out) ||
+ ((mask == SMART_INCOMING) && port->p_hidden_in))) {
+ k++;
+ protocols[port->p_protocol] = 1;
+ }
+ j++;
+ }
+ buffer[0] = '\0';
+ for (i=0; cfg->g_protocols[i].mode != 0; i++) {
+ if (cfg->g_protocols[i].enabled && protocols[cfg->g_protocols[i].mode]) {
+ if (strlen(buffer) +
+ strlen(cfg->g_protocols[i].name) + 3 > sizeof(buffer)) {
+ /* Unlikely, our buffer is too small */
+ memcpy(buffer + sizeof(buffer) - 4, "...", 4);
+ break;
+ }
+ if (buffer[0])
+ strcat(buffer, ", ");
+ strcat(buffer, cfg->g_protocols[i].name);
+ }
+ }
+ LLOG_DEBUG("[%s] %s: %d visible neigh / %d. Protocols: %s.",
+ (mask == SMART_OUTGOING)?"out filter":"in filter",
+ hardware->h_ifname, k, j, buffer[0]?buffer:"(none)");
+}
+