term_t bif_read0_2(term_t Port, term_t Len, process_t *ctx) { apr_status_t rs; apr_size_t size; apr_byte_t *buf; term_t bin; port_t *p; if (!is_port(Port) || !is_int(Len)) return A_BADARG; p = port_lookup(prp_serial(Port)); if (p == 0) return A_BADARG; size = (apr_size_t)int_value(Len); buf = xalloc(proc_gc_pool(ctx), size); rs = p->read(p, buf, &size); if (size == 0 && APR_STATUS_IS_EOF(rs)) result(A_EOF); else if (size == 0 && rs != 0) return decipher_status(rs); else { bin = make_binary(intnum(size), buf, proc_gc_pool(ctx)); result(bin); } return AI_OK; }
/* Assign port to the bridge. */ lagopus_result_t dpmgr_bridge_port_add(struct dpmgr *dpmgr, const char *bridge_name, uint32_t portid, uint32_t port_no) { lagopus_result_t ret; struct port *port; /* Lookup port from the dpmgr. */ port = port_lookup(dpmgr->ports, portid); if (port == NULL) { lagopus_msg_error("Physical port %d is not registered\n", portid); return LAGOPUS_RESULT_NOT_FOUND; } /* Is already part of bridge? */ if (port->bridge != NULL) { lagopus_msg_error("Physical port %d is already assigned\n", portid); return LAGOPUS_RESULT_ALREADY_EXISTS; } port->ofp_port.port_no = port_no; /* Add the port to the bridge. */ ret = bridge_port_add(&dpmgr->bridge_list, bridge_name, port); return ret; }
void test_lagopus_receive_packet(void) { struct lagopus_packet pkt; struct dpmgr *my_dpmgr; struct port nport, *port; struct bridge *bridge; OS_MBUF *m; lagopus_result_t rv; my_dpmgr = dpmgr_alloc(); TEST_ASSERT_NOT_NULL_MESSAGE(my_dpmgr, "alloc error"); rv = dpmgr_bridge_add(my_dpmgr, "br0", 0); TEST_ASSERT_EQUAL_MESSAGE(rv, LAGOPUS_RESULT_OK, "bridge add error\n"); nport.type = LAGOPUS_PORT_TYPE_NULL; /* for test */ nport.ifindex = 0; nport.ofp_port.hw_addr[0] = 1; dpmgr_port_add(my_dpmgr, &nport); nport.ifindex = 1; dpmgr_port_add(my_dpmgr, &nport); rv = dpmgr_bridge_port_add(my_dpmgr, "br0", 0, 1); TEST_ASSERT_EQUAL(rv, LAGOPUS_RESULT_OK); rv = dpmgr_bridge_port_add(my_dpmgr, "br0", 1, 2); TEST_ASSERT_EQUAL(rv, LAGOPUS_RESULT_OK); bridge = dpmgr_bridge_lookup(my_dpmgr, "br0"); TEST_ASSERT_NOT_NULL(bridge); /* prepare packet */ m = calloc(1, sizeof(*m)); TEST_ASSERT_NOT_NULL_MESSAGE(m, "m: calloc error."); m->data = &m->dat[128]; m->data[12] = 0x08; m->data[13] = 0x00; m->data[14] = 0x45; m->data[23] = IPPROTO_TCP; m->refcnt = 2; pkt.cache = NULL; pkt.table_id = 0; pkt.flags = 0; port = port_lookup(bridge->ports, 1); TEST_ASSERT_NOT_NULL_MESSAGE(port, "port lookup error."); lagopus_set_in_port(&pkt, port); TEST_ASSERT_EQUAL_MESSAGE(pkt.in_port, port, "port error."); TEST_ASSERT_EQUAL(pkt.in_port->bridge, bridge); lagopus_packet_init(&pkt, m); lagopus_receive_packet(port, &pkt); TEST_ASSERT_NOT_EQUAL_MESSAGE(pkt.in_port, NULL, "port error."); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "m->refcnt error."); dpmgr_free(my_dpmgr); }
void test_lagopus_match_and_action(void) { struct action_list action_list; struct dpmgr *my_dpmgr; struct bridge *bridge; struct table *table; struct action *action; struct ofp_action_output *action_set; struct port nport, *port; struct lagopus_packet pkt; OS_MBUF *m; /* setup bridge and port */ my_dpmgr = dpmgr_alloc(); dpmgr_bridge_add(my_dpmgr, "br0", 0); nport.type = LAGOPUS_PORT_TYPE_NULL; /* for test */ nport.ifindex = 0; nport.ofp_port.hw_addr[0] = 1; dpmgr_port_add(my_dpmgr, &nport); nport.ifindex = 1; dpmgr_port_add(my_dpmgr, &nport); dpmgr_bridge_port_add(my_dpmgr, "br0", 0, 1); dpmgr_bridge_port_add(my_dpmgr, "br0", 1, 2); bridge = dpmgr_bridge_lookup(my_dpmgr, "br0"); TEST_ASSERT_NOT_NULL(bridge); flowdb_switch_mode_set(bridge->flowdb, SWITCH_MODE_OPENFLOW); table = table_get(bridge->flowdb, 0); table->userdata = new_flowinfo_eth_type(); TAILQ_INIT(&action_list); action = calloc(1, sizeof(*action) + 64); action_set = (struct ofp_action_output *)&action->ofpat; action_set->type = OFPAT_OUTPUT; lagopus_set_action_function(action); TAILQ_INSERT_TAIL(&action_list, action, entry); m = calloc(1, sizeof(*m)); TEST_ASSERT_NOT_NULL_MESSAGE(m, "calloc error."); m->data = &m->dat[128]; m->refcnt = 2; port = port_lookup(bridge->ports, 1); TEST_ASSERT_NOT_NULL(port); lagopus_set_in_port(&pkt, port); TEST_ASSERT_EQUAL(pkt.in_port, port); TEST_ASSERT_EQUAL(pkt.in_port->bridge, bridge); pkt.table_id = 0; lagopus_packet_init(&pkt, m); lagopus_match_and_action(&pkt); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "match_and_action refcnt error."); free(m); dpmgr_free(my_dpmgr); }
lagopus_result_t port_config(struct bridge *bridge, struct ofp_port_mod *port_mod, struct ofp_error *error) { struct port *port; struct ofp_port *ofp_port; uint32_t oldconfig, newconfig; if (port_mod->port_no != OFPP_CONTROLLER) { port = port_lookup(&bridge->ports, port_mod->port_no); if (port == NULL) { error->type = OFPET_PORT_MOD_FAILED; error->code = OFPPMFC_BAD_PORT; lagopus_msg_info("port config: %d: no such port (%d:%d)\n", port_mod->port_no, error->type, error->code); return LAGOPUS_RESULT_OFP_ERROR; } ofp_port = &port->ofp_port; if (port->interface == NULL) { error->type = OFPET_PORT_MOD_FAILED; error->code = OFPPMFC_BAD_HW_ADDR; lagopus_msg_info("port config: %d: do not assigned interface (%d:%d)\n", port_mod->port_no, error->type, error->code); return LAGOPUS_RESULT_OFP_ERROR; } } else { port = NULL; /* XXX shut out warning */ ofp_port = &bridge->controller_port; } /* XXX write lock for thread safe */ if ((port_mod->config & (uint32_t)~port_mod->mask) != 0) { error->type = OFPET_PORT_MOD_FAILED; error->code = OFPPMFC_BAD_CONFIG; lagopus_msg_info("port config: " "config(0x%x) and mask(0x%x) inconsistency (%d:%d)\n", port_mod->config, port_mod->mask, error->type, error->code); return LAGOPUS_RESULT_OFP_ERROR; } oldconfig = ofp_port->config; newconfig = oldconfig; newconfig &= (uint32_t)~port_mod->mask; newconfig |= port_mod->config; ofp_port->config = newconfig; /* advertise, depend on lower driver */ if ((oldconfig != newconfig || ofp_port->advertised != port_mod->advertise) && port_mod->port_no != OFPP_CONTROLLER) { ofp_port->advertised = port_mod->advertise; lagopus_change_physical_port(port); } /* XXX unlock */ return LAGOPUS_RESULT_OK; }
bool port_liveness(struct bridge *bridge, uint32_t port_no) { struct port *port; if (port_no == OFPP_ANY) { return false; } port = port_lookup(bridge->ports, port_no); if (port == NULL) { return false; } if ((port->ofp_port.state & OFPPS_LINK_DOWN) != 0 || (port->ofp_port.config & OFPPC_PORT_DOWN) != 0) { return false; } return true; }
term_t bif_write0_2(term_t Port, term_t Bin, process_t *ctx) { apr_status_t rs; apr_size_t size; port_t *p; if (!is_port(Port) || !is_binary(Bin)) return A_BADARG; p = port_lookup(prp_serial(Port)); if (p == 0) return A_BADARG; size = (apr_size_t)int_value(bin_size(Bin)); rs = p->write(p, bin_data(Bin), &size); if (rs != 0) return decipher_status(rs); //TODO: something may still be written result(intnum(size)); return AI_OK; }
lagopus_result_t port_config(struct bridge *bridge, struct ofp_port_mod *port_mod, struct ofp_error *error) { struct port *port; struct ofp_port *ofp_port; uint32_t oldconfig, newconfig; if (port_mod->port_no != OFPP_CONTROLLER) { port = port_lookup(bridge->ports, port_mod->port_no); if (port == NULL) { ofp_error_set(error, OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT); return LAGOPUS_RESULT_OFP_ERROR; } ofp_port = &port->ofp_port; if (port->interface == NULL) { ofp_error_set(error, OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR); return LAGOPUS_RESULT_OFP_ERROR; } } else { port = NULL; /* XXX shut out warning */ ofp_port = &bridge->controller_port; } /* XXX write lock for thread safe */ if ((port_mod->config & (uint32_t)~port_mod->mask) != 0) { ofp_error_set(error, OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_CONFIG); return LAGOPUS_RESULT_OFP_ERROR; } oldconfig = ofp_port->config; newconfig = oldconfig; newconfig &= (uint32_t)~port_mod->mask; newconfig |= port_mod->config; ofp_port->config = newconfig; /* advertise, depend on lower driver */ if ((oldconfig != newconfig || ofp_port->advertised != port_mod->advertise) && port_mod->port_no != OFPP_CONTROLLER) { ofp_port->advertised = port_mod->advertise; lagopus_change_physical_port(port); } /* XXX unlock */ return LAGOPUS_RESULT_OK; }
term_t bif_sendto4(term_t Sock, term_t RemIP, term_t RemPort, term_t Bin, process_t *ctx) { apr_status_t rs; port_t *port; apr_socket_t *sock; const char *host; int udp_port; apr_sockaddr_t *sa; apr_pool_t *p; if (!is_port(Sock)) return A_BADARG; if (!is_binary(RemIP) || !is_int(RemPort)) return A_BADARG; if (!is_binary(Bin)) return A_BADARG; port = port_lookup(prp_serial(Sock)); if (port == 0) return A_CLOSED; if (!port->is_socket(port)) return A_BADARG; sock = port->get_socket(port); host = (const char *)bin_data(RemIP); udp_port = (apr_port_t)int_value(RemPort); apr_pool_create(&p, 0); rs = apr_sockaddr_info_get(&sa, host, APR_INET, udp_port, 0, p); if (rs == 0) { apr_size_t len = (apr_size_t)int_value(bin_size(Bin)); rs = apr_socket_sendto(sock, sa, 0, (const char *)bin_data(Bin), &len); } if (rs != 0) { apr_pool_destroy(p); return decipher_status(rs); } result(A_OK); return AI_OK; }
void test_set_field_IN_PORT(void) { datastore_bridge_info_t info; struct action_list action_list; struct bridge *bridge; struct port *port; struct action *action; struct ofp_action_set_field *action_set; struct port nport; struct lagopus_packet pkt; OS_MBUF *m; /* setup bridge and port */ memset(&info, 0, sizeof(info)); info.fail_mode = DATASTORE_BRIDGE_FAIL_MODE_SECURE; TEST_ASSERT_EQUAL(dp_bridge_create("br0", &info), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_port_create("port0"), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_port_create("port1"), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_bridge_port_set("br0", "port0", 1), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_bridge_port_set("br0", "port1", 2), LAGOPUS_RESULT_OK); TAILQ_INIT(&action_list); action = calloc(1, sizeof(*action) + 64); action_set = (struct ofp_action_set_field *)&action->ofpat; action_set->type = OFPAT_SET_FIELD; lagopus_set_action_function(action); TAILQ_INSERT_TAIL(&action_list, action, entry); m = calloc(1, sizeof(*m)); TEST_ASSERT_NOT_NULL_MESSAGE(m, "calloc error."); m->data = &m->dat[128]; bridge = dp_bridge_lookup("br0"); TEST_ASSERT_NOT_NULL(bridge); pkt.in_port = port_lookup(bridge->ports, 1); TEST_ASSERT_NOT_NULL(pkt.in_port); lagopus_packet_init(&pkt, m); set_match(action_set->field, 4, OFPXMT_OFB_IN_PORT << 1, 0x00, 0x00, 0x00, 0x02); execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(pkt.in_port->ofp_port.port_no, 2, "SET_FIELD IN_PORT error."); }
void test_lagopus_find_flow(void) { datastore_bridge_info_t info; struct bridge *bridge; struct port *port; struct port nport; struct lagopus_packet *pkt; struct table *table; struct flow *flow; OS_MBUF *m; /* setup bridge and port */ memset(&info, 0, sizeof(info)); info.fail_mode = DATASTORE_BRIDGE_FAIL_MODE_SECURE; TEST_ASSERT_EQUAL(dp_bridge_create("br0", &info), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_port_create("port0"), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_port_create("port1"), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_bridge_port_set("br0", "port0", 1), LAGOPUS_RESULT_OK); TEST_ASSERT_EQUAL(dp_bridge_port_set("br0", "port1", 2), LAGOPUS_RESULT_OK); pkt = alloc_lagopus_packet(); TEST_ASSERT_NOT_NULL_MESSAGE(pkt, "lagopus_alloc_packet error."); m = pkt->mbuf; OS_M_APPEND(m, 64); m->refcnt = 2; bridge = dp_bridge_lookup("br0"); TEST_ASSERT_NOT_NULL(bridge); lagopus_packet_init(pkt, m, port_lookup(&bridge->ports, 1)); table = flowdb_get_table(pkt->in_port->bridge->flowdb, 0); table->userdata = new_flowinfo_eth_type(); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(misc) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(misc) error."); OS_MTOD(m, uint8_t *)[14] = 0x08; OS_MTOD(m, uint8_t *)[15] = 0x06; lagopus_packet_init(pkt, m, &port); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(arp) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(arp) error."); OS_MTOD(m, uint8_t *)[14] = 0x08; OS_MTOD(m, uint8_t *)[15] = 0x00; lagopus_packet_init(pkt, m, port_lookup(&bridge->ports, 1)); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(ipv4) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(ipv4) error."); OS_MTOD(m, uint8_t *)[14] = 0x86; OS_MTOD(m, uint8_t *)[15] = 0xdd; OS_MTOD(m, uint8_t *)[20] = IPPROTO_TCP; lagopus_packet_init(pkt, m, port_lookup(&bridge->ports, 1)); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(ipv6) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(ipv6) error."); OS_MTOD(m, uint8_t *)[14] = 0x88; OS_MTOD(m, uint8_t *)[15] = 0x47; lagopus_packet_init(pkt, m, port_lookup(&bridge->ports, 1)); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(mpls) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(mpls) error."); OS_MTOD(m, uint8_t *)[14] = 0x88; OS_MTOD(m, uint8_t *)[15] = 0x48; lagopus_packet_init(pkt, m, port_lookup(&bridge->ports, 1)); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(mpls-mc) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(mpls-mc) error."); OS_MTOD(m, uint8_t *)[14] = 0x88; OS_MTOD(m, uint8_t *)[15] = 0xe7; lagopus_packet_init(pkt, m, port_lookup(&bridge->ports, 1)); flow = lagopus_find_flow(pkt, table); TEST_ASSERT_EQUAL_MESSAGE(table->lookup_count, 0, "lookup_count(pbb) error."); TEST_ASSERT_NULL_MESSAGE(flow, "flow(pbb) error."); }
void test_action_OUTPUT(void) { struct action_list action_list; struct dpmgr *my_dpmgr; struct bridge *bridge; struct port *port; struct action *action; struct ofp_action_output *action_set; struct port nport; struct lagopus_packet pkt; OS_MBUF *m; /* setup bridge and port */ my_dpmgr = dpmgr_alloc(); dpmgr_bridge_add(my_dpmgr, "br0", 0); nport.type = LAGOPUS_PORT_TYPE_NULL; /* for test */ nport.ofp_port.port_no = 1; nport.ifindex = 0; nport.ofp_port.hw_addr[0] = 1; dpmgr_port_add(my_dpmgr, &nport); port = port_lookup(my_dpmgr->ports, 0); TEST_ASSERT_NOT_NULL(port); port->ofp_port.hw_addr[0] = 0xff; nport.ofp_port.port_no = 2; nport.ifindex = 1; dpmgr_port_add(my_dpmgr, &nport); port = port_lookup(my_dpmgr->ports, 1); TEST_ASSERT_NOT_NULL(port); port->ofp_port.hw_addr[0] = 0xff; dpmgr_bridge_port_add(my_dpmgr, "br0", 0, 1); dpmgr_bridge_port_add(my_dpmgr, "br0", 1, 2); TAILQ_INIT(&action_list); action = calloc(1, sizeof(*action) + 64); action_set = (struct ofp_action_output *)&action->ofpat; action_set->type = OFPAT_OUTPUT; lagopus_set_action_function(action); TAILQ_INSERT_TAIL(&action_list, action, entry); memset(&pkt, 0, sizeof(pkt)); m = calloc(1, sizeof(*m)); TEST_ASSERT_NOT_NULL_MESSAGE(m, "calloc error."); m->data = &m->dat[128]; bridge = dpmgr_bridge_lookup(my_dpmgr, "br0"); TEST_ASSERT_NOT_NULL(bridge); lagopus_set_in_port(&pkt, port_lookup(bridge->ports, 1)); TEST_ASSERT_NOT_NULL(pkt.in_port); lagopus_packet_init(&pkt, m); /* output action always decrement reference count. */ m->refcnt = 2; action_set->port = 1; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = 2; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = OFPP_ALL; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = OFPP_NORMAL; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = OFPP_IN_PORT; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = OFPP_CONTROLLER; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = OFPP_FLOOD; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = OFPP_LOCAL; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); m->refcnt = 2; action_set->port = 0; execute_action(&pkt, &action_list); TEST_ASSERT_EQUAL_MESSAGE(m->refcnt, 1, "OUTPUT refcnt error."); free(m); dpmgr_free(my_dpmgr); }