static void
foreach_route_cb (struct nl_object *object, void *user_data)
{
	ForeachRouteInfo *info = user_data;
	struct rtnl_route *route = (struct rtnl_route *) object;
	struct nl_addr *dst;

	if (info->out_route)
		return;

	if (nm_logging_level_enabled (LOGL_DEBUG))
		dump_route (route);

	if (   info->ifindex > 0
	    && rtnl_route_get_oif (route) != info->ifindex)
		return;

	if (   info->scope != RT_SCOPE_UNIVERSE
	    && rtnl_route_get_scope (route) != info->scope)
		return;

	if (   info->family != AF_UNSPEC
	    && rtnl_route_get_family (route) != info->family)
		return;

	dst = rtnl_route_get_dst (route);

	/* Check for IPv6 LL and MC routes that might need to be ignored */
	if (   (info->family == AF_INET6 || info->family == AF_UNSPEC)
	    && (rtnl_route_get_family (route) == AF_INET6)) {
		struct in6_addr *addr = NULL;

		if (dst)
			addr = nl_addr_get_binary_addr (dst);
		if (addr) {
			if (   IN6_IS_ADDR_LINKLOCAL (addr)
			    || IN6_IS_ADDR_MC_LINKLOCAL (addr)
			    || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (dst) == 8)))
				return;
		}
	}

	info->out_route = info->callback (route, dst, info->iface, info->user_data);
	if (info->out_route) {
		/* Ref the route so it sticks around after the cache is cleared */
		rtnl_route_get (info->out_route);
	}
}
Exemplo n.º 2
0
static int find_route(ib_portid_t * from, ib_portid_t * to, int dump)
{
	Node *node, fromnode, tonode, nextnode;
	Port *port, fromport, toport, nextport;
	Switch sw;
	int maxhops = MAXHOPS;
	int portnum, outport;

	DEBUG("from %s", portid2str(from));

	if (get_node(&fromnode, &fromport, from) < 0 ||
	    get_node(&tonode, &toport, to) < 0) {
		IBWARN("can't reach to/from ports");
		if (!force)
			return -1;
		if (to->lid > 0)
			toport.lid = to->lid;
		IBWARN("Force: look for lid %d", to->lid);
	}

	node = &fromnode;
	port = &fromport;
	portnum = port->portnum;

	dump_endnode(dump, "From", node, port);

	while (maxhops--) {
		if (port->state != 4)
			goto badport;

		if (sameport(port, &toport))
			break;	/* found */

		outport = portnum;
		if (node->type == IB_NODE_SWITCH) {
			DEBUG("switch node");
			if ((outport = switch_lookup(&sw, from, to->lid)) < 0 ||
			    outport > node->numports)
				goto badtbl;

			if (extend_dpath(&from->drpath, outport) < 0)
				goto badpath;

			if (get_node(&nextnode, &nextport, from) < 0) {
				IBWARN("can't reach port at %s",
				       portid2str(from));
				return -1;
			}
			if (outport == 0) {
				if (!sameport(&nextport, &toport))
					goto badtbl;
				else
					break;	/* found SMA port */
			}
		} else if ((node->type == IB_NODE_CA) ||
			   (node->type == IB_NODE_ROUTER)) {
			int ca_src = 0;

			DEBUG("ca or router node");
			if (!sameport(port, &fromport)) {
				IBWARN
				    ("can't continue: reached CA or router port %"
				     PRIx64 ", lid %d", port->portguid,
				     port->lid);
				return -1;
			}
			/* we are at CA or router "from" - go one hop back to (hopefully) a switch */
			if (from->drpath.cnt > 0) {
				DEBUG("ca or router node - return back 1 hop");
				from->drpath.cnt--;
			} else {
				ca_src = 1;
				if (portnum
				    && extend_dpath(&from->drpath, portnum) < 0)
					goto badpath;
			}
			if (get_node(&nextnode, &nextport, from) < 0) {
				IBWARN("can't reach port at %s",
				       portid2str(from));
				return -1;
			}
			/* fix port num to be seen from the CA or router side */
			if (!ca_src)
				nextport.portnum =
				    from->drpath.p[from->drpath.cnt + 1];
		}
		port = &nextport;
		if (port->state != 4)
			goto badoutport;
		node = &nextnode;
		portnum = port->portnum;
		dump_route(dump, node, outport, port);
	}

	if (maxhops <= 0) {
		IBWARN("no route found after %d hops", MAXHOPS);
		return -1;
	}
	dump_endnode(dump, "To", node, port);
	return 0;

badport:
	IBWARN("Bad port state found: node \"%s\" port %d state %d",
	       clean_nodedesc(node->nodedesc), portnum, port->state);
	return -1;
badoutport:
	IBWARN("Bad out port state found: node \"%s\" outport %d state %d",
	       clean_nodedesc(node->nodedesc), outport, port->state);
	return -1;
badtbl:
	IBWARN
	    ("Bad forwarding table entry found at: node \"%s\" lid entry %d is %d (top %d)",
	     clean_nodedesc(node->nodedesc), to->lid, outport, sw.linearFDBtop);
	return -1;
badpath:
	IBWARN("Direct path too long!");
	return -1;
}
Exemplo n.º 3
0
void dump_pim_mrt(FILE *fp)
{
    grpentry_t *g;
    mrtentry_t *r;
    u_int number_of_cache_mirrors = 0;
    u_int number_of_groups = 0;
    cand_rp_t *rp;
    kernel_cache_t *kc;

    fprintf(fp, "Multicast Routing Table ======================================================\n");

    /* TODO: remove the dummy 0.0.0.0 group (first in the chain) */
    for (g = grplist->next; g; g = g->next) {
	number_of_groups++;

	r = g->grp_route;
	if (r) {
	    if (r->flags & MRTF_KERNEL_CACHE) {
		for (kc = r->kernel_cache; kc; kc = kc->next)
		    number_of_cache_mirrors++;
	    }

	    /* Print the (*,G) routing info */
	    fprintf(fp, "----------------------------------- (*,G) ------------------------------------\n");
	    fprintf(fp, "Source           Group            RP Address       Flags\n");
	    fprintf(fp, "---------------  ---------------  ---------------  ---------------------------\n");
	    fprintf(fp, "%-15s  ", "INADDR_ANY");
	    fprintf(fp, "%-15s  ", inet_fmt(g->group, s1, sizeof(s1)));
	    fprintf(fp, "%-15s ", g->active_rp_grp ? inet_fmt(g->rpaddr, s2, sizeof(s2)) : "NULL");

	    dump_route(fp, r);
	}

	/* Print all (S,G) routing info */
	fprintf(fp, "----------------------------------- (S,G) ------------------------------------\n");
	for (r = g->mrtlink; r; r = r->grpnext) {
	    if (r->flags & MRTF_KERNEL_CACHE)
		number_of_cache_mirrors++;

	    /* Print the routing info */
	    fprintf(fp, "Source           Group            RP Address       Flags\n");
	    fprintf(fp, "---------------  ---------------  ---------------  ---------------------------\n");
	    fprintf(fp, "%-15s  ", inet_fmt(r->source->address, s1, sizeof(s1)));
	    fprintf(fp, "%-15s  ", inet_fmt(g->group, s2, sizeof(s2)));
	    fprintf(fp, "%-15s ", g->active_rp_grp ? inet_fmt(g->rpaddr, s2, sizeof(s2)) : "NULL");

	    dump_route(fp, r);
	}
    }/* for all groups */

    /* Print the (*,*,R) routing entries */
    fprintf(fp, "--------------------------------- (*,*,G) ------------------------------------\n");
    for (rp = cand_rp_list; rp; rp = rp->next) {
	r = rp->rpentry->mrtlink;
	if (r) {
	    if (r->flags & MRTF_KERNEL_CACHE) {
		for (kc = r->kernel_cache; kc; kc = kc->next)
		    number_of_cache_mirrors++;
	    }

	    /* Print the (*,*,RP) routing info */
	    fprintf(fp, "Source           Group            RP Address       Flags\n");
	    fprintf(fp, "---------------  ---------------  ---------------  ---------------------------\n");
	    fprintf(fp, "%-15s  ", inet_fmt(r->source->address, s1, sizeof(s1)));
	    fprintf(fp, "%-15s  ", "INADDR_ANY");
	    fprintf(fp, "%-15s ", "");

	    dump_route(fp, r);
	}
    } /* For all (*,*,RP) */

    fprintf(fp, "Number of Groups: %u\n", number_of_groups);
    fprintf(fp, "Number of Cache MIRRORs: %u\n", number_of_cache_mirrors);
    fprintf(fp, "------------------------------------------------------------------------------\n\n");
}