Пример #1
0
/* 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;
}
Пример #2
0
/*
 * 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);
}