/* route -A inet4 add vrf NUMBER IP4NET gw IP4ADDR dev DEV */ void f_route_add_vrf(struct cli_conn *conn, const char *s) { uint32_t gwaddr, destaddr; int a, b, c, d, e, f, g, h, port, mlen, vrf, vlan; char dev[16]; if (sscanf(s, "%d %d.%d.%d.%d/%d %d.%d.%d.%d %s", &vrf, &a, &b, &c, &d, &mlen, &e, &f, &g, &h, dev) != 11) return; destaddr = odp_cpu_to_be_32((a << 24) | (b << 16) | (c << 8) | d); gwaddr = odp_cpu_to_be_32((e << 24) | (f << 16) | (g << 8) | h); port = ofp_name_to_port_vlan(dev, &vlan); if (port < 0 || port >= ofp_get_num_ports()) { ofp_sendf(conn->fd, "Invalid port!\r\n"); sendcrlf(conn); return; } ofp_set_route_params(OFP_ROUTE_ADD, vrf, vlan, port, destaddr, mlen, gwaddr); sendcrlf(conn); }
/* route -A inet4 delete vrf NUMBER IP4NET */ void f_route_del_vrf(struct cli_conn *conn, const char *s) { uint32_t destaddr; int a, b, c, d, mlen, vrf; if (sscanf(s, "%d %d.%d.%d.%d/%d", &vrf, &a, &b, &c, &d, &mlen) != 6) return; destaddr = odp_cpu_to_be_32((a << 24) | (b << 16) | (c << 8) | d); ofp_set_route_params(OFP_ROUTE_DEL, vrf, 0 /*vlan*/, 0 /*port*/, destaddr, mlen, 0 /*gw*/); sendcrlf(conn); }
static void test_ofp_add_route(uint32_t port, uint32_t vrf, uint32_t vlan, uint32_t destination, uint32_t mask_len, uint32_t rt_dst_len, uint32_t gw) { /* add/test only IPv4 routes and not IPv6 or DEFAULT routes(rt_dst=0)*/ CU_ASSERT_EQUAL(rt_dst_len, 4); if (rt_dst_len == 4) { ofp_set_route_params(OFP_ROUTE_ADD, vrf, vlan, port, destination, mask_len, gw); } uint32_t flags; struct ofp_nh_entry *node = ofp_get_next_hop(vrf, destination, &flags); CU_ASSERT_EQUAL(node->gw, gw); CU_ASSERT_EQUAL(node->port, port); CU_ASSERT_EQUAL(node->vlan, vlan); }
int ofp_ioctl(int sockfd, int request, ...) { va_list ap; void *data; struct ofp_ifnet *iface = NULL; struct socket *so = ofp_get_sock_by_fd(sockfd); if (!so) { ofp_errno = OFP_EBADF; return -1; } va_start(ap, request); data = va_arg(ap, void *); va_end(ap); if (request == (int)(OFP_SIOCGIFCONF)) { ofp_errno = ((*so->so_proto->pr_usrreqs->pru_control) (so, request, data, NULL, NULL)); } else if (OFP_IOCGROUP(request) == 'i') { /* All the interface requests start with interface name */ int port, vlan = 0; char *name = data; if (get_port_vlan_by_name(name, &port, &vlan) < 0) { ofp_errno = OFP_EBADF; return -1; } if (request == (int)(OFP_SIOCSIFTUN)) { struct ofp_in_tunreq *treq = data; const char *retstr = ofp_config_interface_up_tun (port, vlan, treq->iftun_vrf, treq->iftun_local_addr.sin_addr.s_addr, treq->iftun_remote_addr.sin_addr.s_addr, treq->iftun_p2p_addr.sin_addr.s_addr, treq->iftun_addr.sin_addr.s_addr, 30); if (!retstr) ofp_errno = 0; else ofp_errno = OFP_EBADMSG; } else { iface = ofp_get_ifnet(port, vlan); if (so->so_proto->pr_usrreqs->pru_control) ofp_errno = ((*so->so_proto->pr_usrreqs->pru_control) (so, request, data, iface, NULL)); else ofp_errno = OFP_EOPNOTSUPP; } } else if (OFP_IOCGROUP(request) == 'r') { int port = 0, vlan = 0; struct ofp_rtentry *rt = data; uint32_t dst = ((struct ofp_sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr; uint32_t mask = ((struct ofp_sockaddr_in *)&rt->rt_genmask)->sin_addr.s_addr; uint32_t gw = ((struct ofp_sockaddr_in *)&rt->rt_gateway)->sin_addr.s_addr; uint32_t maskcpu = odp_be_to_cpu_32(mask); uint32_t mlen = 0; if (request != (int)OFP_SIOCADDRT && request != (int)OFP_SIOCDELRT) { ofp_errno = OFP_EBADF; return -1; } if (request == (int)OFP_SIOCADDRT) { if (rt->rt_dev) { if (get_port_vlan_by_name(rt->rt_dev, &port, &vlan) < 0) { ofp_errno = OFP_EBADF; return -1; } } else { uint32_t flags; struct ofp_nh_entry *nh = ofp_get_next_hop(rt->rt_vrf, gw, &flags); if (!nh) { ofp_errno = OFP_EBADF; return -1; } port = nh->port; vlan = nh->vlan; } } while (maskcpu) { mlen++; maskcpu <<= 1; } ofp_set_route_params((request == (int) OFP_SIOCADDRT) ? OFP_ROUTE_ADD : OFP_ROUTE_DEL, rt->rt_vrf, vlan, port, dst, mlen, gw, (request == (int) OFP_SIOCADDRT) ? (gw ? OFP_RTF_GATEWAY : OFP_RTF_NET) : 0); } else { ofp_errno = ofp_soo_ioctl(so, request, data, NULL, NULL); } if (ofp_errno) return -1; return 0; }