예제 #1
0
static void
neigh_delete(switchlink_handle_t vrf_h, switchlink_ip_addr_t *ipaddr,
             switchlink_handle_t intf_h) {
    switchlink_db_neigh_info_t neigh_info;
    switchlink_db_status_t status;

    memset(&neigh_info, 0, sizeof(switchlink_db_neigh_info_t));
    neigh_info.vrf_h = vrf_h;
    neigh_info.intf_h = intf_h;
    memcpy(&(neigh_info.ip_addr), ipaddr, sizeof(switchlink_ip_addr_t));
    status = switchlink_db_neighbor_get_info(&neigh_info);
    if (status != SWITCHLINK_DB_STATUS_SUCCESS) {
        return;
    }

    switchlink_neighbor_delete(&neigh_info);
    switchlink_nexthop_delete(&neigh_info);
    switchlink_db_neighbor_delete(&neigh_info);

    // delete the host route
    route_delete(g_default_vrf_h, ipaddr);
}
예제 #2
0
파일: sharp_zebra.c 프로젝트: ton31337/frr
void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
				uint8_t instance, uint32_t routes)
{
	uint32_t temp, i;
	bool v4 = false;

	zlog_debug("Removing %u routes", routes);

	if (p->family == AF_INET) {
		v4 = true;
		temp = ntohl(p->u.prefix4.s_addr);
	} else
		temp = ntohl(p->u.val32[3]);

	monotime(&sg.r.t_start);
	for (i = 0; i < routes; i++) {
		route_delete(p, vrf_id, (uint8_t)instance);
		if (v4)
			p->u.prefix4.s_addr = htonl(++temp);
		else
			p->u.val32[3] = htonl(++temp);
	}
}
예제 #3
0
int main(int argc, char *argv[])
{
    const char  rtnet_dev[] = "/dev/rtnet";


    if (argc == 1)
        print_routes();

    if ((strcmp(argv[1], "--help") == 0) || (argc < 3))
        help();

    f = open(rtnet_dev, O_RDWR);
    if (f < 0) {
        perror(rtnet_dev);
        exit(1);
    }

    /* add host routes from file? */
    if (strcmp(argv[1], "-f") == 0)
        route_listadd(argv[2]);

    /* second argument is now always an IP address */
    if (!inet_aton(argv[2], &addr))
        help();

    if (strcmp(argv[1], "solicit") == 0)
        route_solicit(argc, argv);
    if (strcmp(argv[1], "add") == 0)
        route_add(argc, argv);
    if (strcmp(argv[1], "del") == 0)
        route_delete(argc, argv);

    help();

    return 0;
}
void
process_address_msg(struct nlmsghdr *nlmsg, int type) {
    int hdrlen, attrlen;
    struct nlattr *attr;
    struct ifaddrmsg *addrmsg;
    bool addr_valid = false;
    switchlink_ip_addr_t addr;

    assert((type == RTM_NEWADDR) || (type == RTM_DELADDR));
    addrmsg = nlmsg_data(nlmsg);
    hdrlen = sizeof(struct ifaddrmsg);
    NL_LOG_DEBUG(("%saddr: family = %d, prefixlen = %d, flags = 0x%x, "
                  "scope = 0x%x ifindex = %d\n",
                  ((type == RTM_NEWADDR) ? "new" : "del"), addrmsg->ifa_family,
                  addrmsg->ifa_prefixlen, addrmsg->ifa_flags,
                  addrmsg->ifa_scope, addrmsg->ifa_index));

    if ((addrmsg->ifa_family != AF_INET) && (addrmsg->ifa_family != AF_INET6)) {
        // an address family that we are not interested in, skip
        return;
    }

    switchlink_db_status_t status;
    switchlink_intf_type_t intf_type = SWITCHLINK_INTF_TYPE_NONE;
    switchlink_handle_t intf_h = 0;
    bool create_l3vi = false;

    switchlink_db_interface_info_t ifinfo;
    status = switchlink_db_interface_get_info(addrmsg->ifa_index, &ifinfo);
    if (status == SWITCHLINK_DB_STATUS_SUCCESS) {
        intf_type = ifinfo.intf_type;
        intf_h = ifinfo.intf_h;
    } else {
        switchlink_db_bridge_info_t brinfo;
        status = switchlink_db_bridge_get_info(addrmsg->ifa_index, &brinfo);
        if (status == SWITCHLINK_DB_STATUS_SUCCESS) {
            create_l3vi = true;
        } else {
            // an interface that we are not interested in, skip
            return;
        }
    }
    if (strcmp(ifinfo.ifname, SWITCHLINK_CPU_INTERFACE_NAME) == 0) {
        // address on CPU interface, skip
        return;
    }

    attrlen = nlmsg_attrlen(nlmsg, hdrlen);
    attr = nlmsg_attrdata(nlmsg, hdrlen);
    while (nla_ok(attr, attrlen)) {
        int attr_type = nla_type(attr);
        switch (attr_type) {
            case IFA_ADDRESS:
                addr_valid = true;
                memset(&addr, 0, sizeof(switchlink_ip_addr_t));
                addr.family = addrmsg->ifa_family;
                addr.prefix_len = addrmsg->ifa_prefixlen;
                if (addrmsg->ifa_family == AF_INET) {
                    addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr));
                } else {
                    memcpy(&(addr.ip.v6addr), nla_data(attr), nla_len(attr));
                }
                break;
            default:
                NL_LOG_DEBUG(("addr: skipping attr(%d)\n", attr_type));
                break;
        }
        attr = nla_next(attr, &attrlen);
    }

    if (type == RTM_NEWADDR) {
        if ((addrmsg->ifa_family == AF_INET) ||
            ((addrmsg->ifa_family == AF_INET6) &&
             !IN6_IS_ADDR_LINKLOCAL(&(addr.ip.v6addr)))) {
            if (create_l3vi) {
                interface_create_l3vi(addrmsg->ifa_index);
                status = switchlink_db_interface_get_info(addrmsg->ifa_index, &ifinfo);
                assert(status == SWITCHLINK_DB_STATUS_SUCCESS);
                intf_h = ifinfo.intf_h;
            } else {
                if (intf_type == SWITCHLINK_INTF_TYPE_L2_ACCESS) {
                    interface_change_type(addrmsg->ifa_index,
                                          SWITCHLINK_INTF_TYPE_L3);
                }
            }
        }
        if (addr_valid) {
            switchlink_ip_addr_t null_gateway;
            memset(&null_gateway, 0, sizeof(null_gateway));
            null_gateway.family = addr.family;

            // add the subnet route
            route_create(g_default_vrf_h, &addr, &null_gateway, 0, intf_h);

            // add the interface route
            if (addrmsg->ifa_family == AF_INET) {
                addr.prefix_len = 32;
            } else {
                addr.prefix_len = 128;
            }
            route_create(g_default_vrf_h, &addr, &null_gateway, 0, intf_h);
        }
    } else {
        if (addr_valid) {
            // remove the subnet route
            route_delete(g_default_vrf_h, &addr);

            // remove the interface route
            if (addrmsg->ifa_family == AF_INET) {
                addr.prefix_len = 32;
            } else {
                addr.prefix_len = 128;
            }
            route_delete(g_default_vrf_h, &addr);
        }
    }
}
예제 #5
0
void
route_create(switchlink_handle_t vrf_h, switchlink_ip_addr_t *dst,
             switchlink_ip_addr_t *gateway, switchlink_handle_t ecmp_h,
             switchlink_handle_t intf_h) {
    if (!dst || (!gateway && !ecmp_h)) {
        if (ecmp_h) {
            ecmp_delete(ecmp_h);
        }
        return;
    }

    bool ecmp_valid = false;
    switchlink_handle_t nhop_h = 0;
    if (!ecmp_h) {
        switchlink_db_neigh_info_t neigh_info;
        memset(&neigh_info, 0, sizeof(switchlink_db_neigh_info_t));
        memcpy(&(neigh_info.ip_addr), gateway, sizeof(switchlink_ip_addr_t));
        neigh_info.intf_h = intf_h;
        neigh_info.vrf_h = vrf_h;
        switchlink_db_status_t status;
        status = switchlink_db_neighbor_get_info(&neigh_info);
        if (status == SWITCHLINK_DB_STATUS_SUCCESS) {
            nhop_h = neigh_info.nhop_h;
        } else {
            nhop_h = g_cpu_rx_nhop_h;
        }
        ecmp_valid = false;
    } else {
        ecmp_valid = true;
        nhop_h = ecmp_h;
    }

    // get the route from the db (if it already exists)
    switchlink_db_route_info_t route_info;
    memset(&route_info, 0, sizeof(switchlink_db_route_info_t));
    route_info.vrf_h = vrf_h;
    memcpy(&(route_info.ip_addr), dst, sizeof(switchlink_ip_addr_t));
    switchlink_db_status_t status = switchlink_db_route_get_info(&route_info);
    if (status == SWITCHLINK_DB_STATUS_SUCCESS) {
        if ((route_info.ecmp == ecmp_valid) && (route_info.nhop_h == nhop_h)) {
            // no change
            return;
        }
        // nexthop has change, delete the current route
        route_delete(vrf_h, dst);
    }

    memset(&route_info, 0, sizeof(switchlink_db_route_info_t));
    route_info.vrf_h = vrf_h;
    memcpy(&(route_info.ip_addr), dst, sizeof(switchlink_ip_addr_t));
    route_info.ecmp = ecmp_valid;
    route_info.nhop_h = nhop_h;

    // add the route
    if (switchlink_route_create(&route_info) == -1) {
        if (route_info.ecmp) {
            ecmp_delete(route_info.nhop_h);
        }
        return;
    }

    // add the route to the db
    if (switchlink_db_route_add(&route_info) == SWITCHLINK_DB_STATUS_SUCCESS) {
        if (route_info.ecmp) {
            switchlink_db_ecmp_ref_inc(route_info.nhop_h);
        }
    }
}
예제 #6
0
void
process_route_msg(struct nlmsghdr *nlmsg, int type) {
    int hdrlen, attrlen;
    struct nlattr *attr;
    struct rtmsg *rmsg;
    bool src_valid = false;
    bool dst_valid = false;
    bool gateway_valid = false;
    switchlink_handle_t ecmp_h = 0;
    switchlink_ip_addr_t src_addr;
    switchlink_ip_addr_t dst_addr;
    switchlink_ip_addr_t gateway_addr;
    switchlink_db_interface_info_t ifinfo;
    uint8_t af = AF_UNSPEC;
    bool oif_valid = false;
    uint32_t oif = 0;

    switchlink_handle_t oifl_h = 0;
    bool ip_multicast = false;
    bool iif_valid = false;
    uint32_t iif = 0;

    assert((type == RTM_NEWROUTE) || (type == RTM_DELROUTE));
    rmsg = nlmsg_data(nlmsg);
    hdrlen = sizeof(struct rtmsg);
    NL_LOG_DEBUG(("%sroute: family = %d, dst_len = %d, src_len = %d, tos = %d, "
                  "table = %d, proto = %d, scope = %d, type = %d, "
                  "flags = 0x%x\n",
                  ((type == RTM_NEWROUTE) ? "new" : "del"),
                  rmsg->rtm_family, rmsg->rtm_dst_len, rmsg->rtm_src_len,
                  rmsg->rtm_tos, rmsg->rtm_table, rmsg->rtm_protocol,
                  rmsg->rtm_scope, rmsg->rtm_type, rmsg->rtm_flags));

    if (rmsg->rtm_family > AF_MAX) {
        assert(rmsg->rtm_type == RTN_MULTICAST);
        if (rmsg->rtm_family == RTNL_FAMILY_IPMR) {
            af = AF_INET;
        } else if (rmsg->rtm_family == RTNL_FAMILY_IP6MR) {
            af = AF_INET6;
        }
        ip_multicast = true;
    } else {
        af = rmsg->rtm_family;
    }

    if ((af != AF_INET) && (af != AF_INET6)) {
        return;
    }

    memset(&dst_addr, 0, sizeof(switchlink_ip_addr_t));
    memset(&gateway_addr, 0, sizeof(switchlink_ip_addr_t));

    attrlen = nlmsg_attrlen(nlmsg, hdrlen);
    attr = nlmsg_attrdata(nlmsg, hdrlen);
    while (nla_ok(attr, attrlen)) {
        int attr_type = nla_type(attr);
        switch (attr_type) {
            case RTA_SRC:
                src_valid = true;
                memset(&src_addr, 0, sizeof(switchlink_ip_addr_t));
                src_addr.family = af;
                src_addr.prefix_len = rmsg->rtm_src_len;
                if (src_addr.family == AF_INET) {
                    src_addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr));
                } else {
                    memcpy(&(src_addr.ip.v6addr), nla_data(attr),
                           nla_len(attr));
                }
                break;
            case RTA_DST:
                dst_valid = true;
                memset(&dst_addr, 0, sizeof(switchlink_ip_addr_t));
                dst_addr.family = af;
                dst_addr.prefix_len = rmsg->rtm_dst_len;
                if (dst_addr.family == AF_INET) {
                    dst_addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr));
                } else {
                    memcpy(&(dst_addr.ip.v6addr), nla_data(attr),
                           nla_len(attr));
                }
                break;
            case RTA_GATEWAY:
                gateway_valid = true;
                memset(&gateway_addr, 0, sizeof(switchlink_ip_addr_t));
                gateway_addr.family = rmsg->rtm_family;
                if (rmsg->rtm_family == AF_INET) {
                    gateway_addr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr));
                    gateway_addr.prefix_len = 32;
                } else {
                    memcpy(&(gateway_addr.ip.v6addr), nla_data(attr),
                           nla_len(attr));
                    gateway_addr.prefix_len = 128;
                }
                break;
            case RTA_MULTIPATH:
                if (ip_multicast) {
                    oifl_h = process_oif_list(attr, g_default_vrf_h);
                } else {
                    ecmp_h = process_ecmp(af, attr, g_default_vrf_h);
                }
                break;
            case RTA_OIF:
                oif_valid = true;
                oif = nla_get_u32(attr);
                break;
            case RTA_IIF:
                iif_valid = true;
                iif = nla_get_u32(attr);
                break;
            default:
                NL_LOG_DEBUG(("route: skipping attr(%d)\n", attr_type));
                break;
        }
        attr = nla_next(attr, &attrlen);
    }

    if (rmsg->rtm_dst_len == 0) {
        dst_valid = true;
        memset(&dst_addr, 0, sizeof(switchlink_ip_addr_t));
        dst_addr.family = af;
        dst_addr.prefix_len = 0;
    }

    if (!ip_multicast) {
        if (type == RTM_NEWROUTE) {
            memset(&ifinfo, 0, sizeof(ifinfo));
            if (oif_valid) {
                switchlink_db_status_t status;
                status = switchlink_db_interface_get_info(oif, &ifinfo);
                if (status != SWITCHLINK_DB_STATUS_SUCCESS) {
                    NL_LOG_DEBUG(("route: switchlink_db_interface_get_info "
                                  "(unicast) failed\n"));
                    return;
                }
            }
            route_create(g_default_vrf_h, (dst_valid ? &dst_addr : NULL),
                         (gateway_valid ? &gateway_addr : NULL),
                         ecmp_h, ifinfo.intf_h);
        } else {
            route_delete(g_default_vrf_h, (dst_valid ? &dst_addr : NULL));
        }
    } else {
        if (rmsg->rtm_src_len == 0) {
            src_valid = true;
            memset(&src_addr, 0, sizeof(switchlink_ip_addr_t));
            src_addr.family = af;
            src_addr.prefix_len = 0;
        }

        if (type == RTM_NEWROUTE) {
            if (!iif_valid || !oifl_h) {
                // multicast route cache is not resolved yet
                return;
            }
            switchlink_db_status_t status;
            status = switchlink_db_interface_get_info(iif, &ifinfo);
            if (status != SWITCHLINK_DB_STATUS_SUCCESS) {
                NL_LOG_DEBUG(("route: switchlink_db_interface_get_info "
                              "(multicast) failed\n"));
                return;
            }
            mroute_create(g_default_vrf_h, (src_valid ? &src_addr : NULL),
                          (dst_valid ? &dst_addr : NULL),
                          ifinfo.intf_h, oifl_h);
        } else {
            mroute_delete(g_default_vrf_h, (src_valid ? &src_addr : NULL),
                          (dst_valid ? &dst_addr : NULL));
        }
    }
}