+ printf("Done\n");
+}
+
+void
+attach_port(char *identifier)
+{
+ portid_t pi;
+ struct rte_dev_iterator iterator;
+
+ printf("Attaching a new port...\n");
+
+ if (identifier == NULL) {
+ printf("Invalid parameters are specified\n");
+ return;
+ }
+
+ if (rte_dev_probe(identifier) != 0) {
+ TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
+ return;
+ }
+
+ /* first attach mode: event */
+ if (setup_on_probe_event) {
+ /* new ports are detected on RTE_ETH_EVENT_NEW event */
+ for (pi = 0; pi < RTE_MAX_ETHPORTS; pi++)
+ if (ports[pi].port_status == RTE_PORT_HANDLING &&
+ ports[pi].need_setup != 0)
+ setup_attached_port(pi);
+ return;
+ }
+
+ /* second attach mode: iterator */
+ RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator) {
+ /* setup ports matching the devargs used for probing */
+ if (port_is_forwarding(pi))
+ continue; /* port was already attached before */
+ setup_attached_port(pi);
+ }
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+ unsigned int socket_id;
+
+ socket_id = (unsigned)rte_eth_dev_socket_id(pi);
+ /* if socket_id is invalid, set to the first available socket. */
+ if (check_socket_id(socket_id) < 0)
+ socket_id = socket_ids[0];
+ reconfig(pi, socket_id);
+ rte_eth_promiscuous_enable(pi);
+
+ ports_ids[nb_ports++] = pi;
+ fwd_ports_ids[nb_fwd_ports++] = pi;
+ nb_cfg_ports = nb_fwd_ports;
+ ports[pi].need_setup = 0;
+ ports[pi].port_status = RTE_PORT_STOPPED;
+
+ printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
+ printf("Done\n");
+}
+
+void
+detach_port_device(portid_t port_id)
+{
+ struct rte_device *dev;
+ portid_t sibling;
+
+ printf("Removing a device...\n");
+
+ dev = rte_eth_devices[port_id].device;
+ if (dev == NULL) {
+ printf("Device already removed\n");
+ return;
+ }
+
+ if (ports[port_id].port_status != RTE_PORT_CLOSED) {
+ if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+ printf("Port not stopped\n");
+ return;
+ }
+ printf("Port was not closed\n");
+ if (ports[port_id].flow_list)
+ port_flow_flush(port_id);
+ }
+
+ if (rte_dev_remove(dev) != 0) {
+ TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name);
+ return;
+ }
+
+ for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++) {
+ if (rte_eth_devices[sibling].device != dev)
+ continue;
+ /* reset mapping between old ports and removed device */
+ rte_eth_devices[sibling].device = NULL;
+ if (ports[sibling].port_status != RTE_PORT_CLOSED) {
+ /* sibling ports are forced to be closed */
+ ports[sibling].port_status = RTE_PORT_CLOSED;
+ printf("Port %u is closed\n", sibling);
+ }
+ }
+
+ remove_invalid_ports();
+
+ printf("Device of port %u is detached\n", port_id);
+ printf("Now total ports is %d\n", nb_ports);
+ printf("Done\n");
+ return;