/* Receive the ethernet address to which the server should send packets. */ static int wire_server_receive_hw_address(struct wire_server *wire_server) { enum wire_op_t op = WIRE_INVALID; void *buf = NULL; int buf_len = -1; if (wire_conn_read(wire_server->wire_conn, &op, &buf, &buf_len)) return STATUS_ERR; if (op != WIRE_HARDWARE_ADDR) { fprintf(stderr, "bad wire client: expected WIRE_HARDWARE_ADDR\n"); return STATUS_ERR; } if (buf_len != sizeof(wire_server->client_ether_addr)) { fprintf(stderr, "bad wire client: bad hw address length\n"); return STATUS_ERR; } ether_copy(&wire_server->client_ether_addr, buf); return STATUS_OK; }
/* * Add or remove multicast address(es). * * Returns 0 on success, 1 on failure. */ int vsw_add_rem_mcst(vnet_mcast_msg_t *mcst_pkt, vsw_port_t *port) { mcst_addr_t *mcst_p = NULL; vsw_t *vswp = port->p_vswp; uint64_t addr = 0x0; int i; D1(vswp, "%s: enter", __func__); D2(vswp, "%s: %d addresses", __func__, mcst_pkt->count); for (i = 0; i < mcst_pkt->count; i++) { /* * Convert address into form that can be used * as hash table key. */ KEY_HASH(addr, &(mcst_pkt->mca[i])); /* * Add or delete the specified address/port combination. */ if (mcst_pkt->set == 0x1) { D3(vswp, "%s: adding multicast address 0x%llx for " "port %ld", __func__, addr, port->p_instance); if (vsw_add_mcst(vswp, VSW_VNETPORT, addr, port) == 0) { /* * Update the list of multicast * addresses contained within the * port structure to include this new * one. */ mcst_p = kmem_zalloc(sizeof (mcst_addr_t), KM_NOSLEEP); if (mcst_p == NULL) { DERR(vswp, "%s: unable to alloc mem", __func__); (void) vsw_del_mcst(vswp, VSW_VNETPORT, addr, port); return (1); } mcst_p->nextp = NULL; mcst_p->addr = addr; ether_copy(&mcst_pkt->mca[i], &mcst_p->mca); /* * Program the address into HW. If the addr * has already been programmed then the MAC * just increments a ref counter (which is * used when the address is being deleted) */ if (vsw_mac_multicast_add(vswp, port, mcst_p, VSW_VNETPORT)) { (void) vsw_del_mcst(vswp, VSW_VNETPORT, addr, port); kmem_free(mcst_p, sizeof (*mcst_p)); return (1); } mutex_enter(&port->mca_lock); mcst_p->nextp = port->mcap; port->mcap = mcst_p; mutex_exit(&port->mca_lock); } else { DERR(vswp, "%s: error adding multicast " "address 0x%llx for port %ld", __func__, addr, port->p_instance); return (1); } } else { /* * Delete an entry from the multicast hash * table and update the address list * appropriately. */ if (vsw_del_mcst(vswp, VSW_VNETPORT, addr, port) == 0) { D3(vswp, "%s: deleting multicast address " "0x%llx for port %ld", __func__, addr, port->p_instance); mcst_p = vsw_del_addr(VSW_VNETPORT, port, addr); ASSERT(mcst_p != NULL); /* * Remove the address from HW. The address * will actually only be removed once the ref * count within the MAC layer has dropped to * zero. I.e. we can safely call this fn even * if other ports are interested in this * address. */ vsw_mac_multicast_remove(vswp, port, mcst_p, VSW_VNETPORT); kmem_free(mcst_p, sizeof (*mcst_p)); } else { DERR(vswp, "%s: error deleting multicast " "addr 0x%llx for port %ld", __func__, addr, port->p_instance); return (1); } } } D1(vswp, "%s: exit", __func__); return (0); }