Print this page
feth prototype
@@ -61,10 +61,11 @@
#include <libdlvnic.h>
#include <libdlib.h>
#include <libdlether.h>
#include <libdliptun.h>
#include <libdlsim.h>
+#include <libdlfeth.h>
#include <libdlbridge.h>
#include <libdloverlay.h>
#include <libinetutil.h>
#include <libvrrpadm.h>
#include <bsm/adt.h>
@@ -224,10 +225,11 @@
static cmdfunc_t do_create_part, do_delete_part, do_show_part, do_show_ib;
static cmdfunc_t do_up_part;
static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub;
static cmdfunc_t do_create_simnet, do_modify_simnet;
static cmdfunc_t do_delete_simnet, do_show_simnet, do_up_simnet;
+static cmdfunc_t do_create_feth, do_delete_feth, do_show_feth, do_up_feth;
static cmdfunc_t do_show_usage;
static cmdfunc_t do_create_bridge, do_modify_bridge, do_delete_bridge;
static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge;
static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun;
static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun;
@@ -389,10 +391,19 @@
{ "create-simnet", do_create_simnet, NULL },
{ "modify-simnet", do_modify_simnet, NULL },
{ "delete-simnet", do_delete_simnet, NULL },
{ "show-simnet", do_show_simnet, NULL },
{ "up-simnet", do_up_simnet, NULL },
+ { "create-feth", do_create_feth,
+ " create-feth [-t] [-s] [-R <root-dir>] [-m <mac address>] "
+ "<feth-link>" },
+ { "delete-feth", do_delete_feth,
+ " delete-feth [-R <root-dir>] <feth-link>" },
+ { "show-feth", do_show_feth,
+ " show-feth [-p] [-o <field>,...] [-P] [<feth-link>]" },
+ { "up-feth", do_up_feth,
+ " up-feth <feth-link>\n" },
{ "create-bridge", do_create_bridge,
" create-bridge [-R <root-dir>] [-P <protect>] "
"[-p <priority>]\n"
"\t\t [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n"
"\t\t [-f <force-protocol>] [-l <link>]... <bridge>" },
@@ -587,10 +598,16 @@
{"media", required_argument, 0, 'm' },
{"peer", required_argument, 0, 'p' },
{ NULL, 0, NULL, 0 }
};
+static const struct option feth_lopts[] = {
+ {"temporary", no_argument,0, 't' },
+ {"root-dir", required_argument, 0, 'R' },
+ { NULL, 0, NULL, 0 }
+};
+
static const struct option bridge_lopts[] = {
{ "protect", required_argument, 0, 'P' },
{ "root-dir", required_argument, 0, 'R' },
{ "forward-delay", required_argument, 0, 'd' },
{ "force-protocol", required_argument, 0, 'f' },
@@ -1136,10 +1153,28 @@
offsetof(simnet_fields_buf_t, simnet_otherlink), print_default_cb},
{ NULL, 0, 0, NULL}}
;
/*
+ * structures for 'dladm show-feth'
+ */
+
+typedef struct feth_fields_buf_s
+{
+ char feth_name[DLPI_LINKNAME_MAX];
+ char feth_macaddr[18];
+} feth_fields_buf_t;
+
+static const ofmt_field_t feth_fields[] = {
+ { "LINK",12,
+ offsetof(feth_fields_buf_t, feth_name), print_default_cb},
+ { "MACADDRESS",18,
+ offsetof(feth_fields_buf_t, feth_macaddr), print_default_cb},
+ { NULL,0, 0, NULL}}
+;
+
+/*
* structures for 'dladm show-usage'
*/
typedef struct usage_fields_buf_s {
char usage_link[12];
@@ -2895,11 +2930,16 @@
DLADM_STATUS_OK)
(void) strcpy(lbuf->link_over, "?");
}
break;
}
+
+ case DATALINK_CLASS_FETH: {
+ (void) strcpy(lbuf->link_over, "--");
+ break;
}
+ }
}
static dladm_status_t
print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf)
{
@@ -5751,11 +5791,257 @@
}
}
ofmt_close(ofmt);
}
+/* ARGSUSED */
static void
+do_up_feth(int argc, char *argv[], const char *use)
+{
+ (void) dladm_feth_up(handle, DATALINK_ALL_LINKID, 0);
+}
+
+static void
+do_create_feth(int argc, char *argv[], const char *use)
+{
+ uint32_t flags;
+ char *altroot = NULL;
+ int option;
+ dladm_status_t status;
+ char name[MAXLINKNAMELEN];
+ boolean_t mac_provided = B_FALSE;
+ boolean_t mac_fixed;
+ uint8_t mac_addr[ETHERADDRL];
+
+ name[0] = '\0';
+ flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":tsR:m:",
+ feth_lopts, NULL)) != -1) {
+ switch (option) {
+ case 't':
+ flags &= ~DLADM_OPT_PERSIST;
+ break;
+ case 's':
+ flags |= FETH_FLAG_SINGLESHOT;
+ break;
+ case 'R':
+ altroot = optarg;
+ break;
+ case 'm':
+ if (mac_provided == B_TRUE)
+ die("cannot specify -m option twice");
+
+ if (!dladm_aggr_str2macaddr(optarg, &mac_fixed, mac_addr)) {
+ die("invalid MAC address");
+ }
+ mac_provided = B_TRUE;
+ printf("have mac address\n");
+ break;
+ default:
+ die_opterr(optopt, option, use);
+ }
+ }
+
+ /* the simnet id is the required operand */
+ if (optind != (argc - 1))
+ usage();
+
+ if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
+ die("link name too long '%s'", argv[optind]);
+
+ if (!dladm_valid_linkname(name))
+ die("invalid link name '%s'", name);
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ if(mac_provided)
+ status = dladm_feth_create_mac(handle, name, flags, mac_addr);
+ else
+ status = dladm_feth_create(handle, name, flags);
+ if (status != DLADM_STATUS_OK)
+ die_dlerr(status, "feth creation failed");
+}
+
+static void
+do_delete_feth(int argc, char *argv[], const char *use)
+{
+ int option;
+ uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+ datalink_id_t linkid;
+ char *altroot = NULL;
+ dladm_status_t status;
+ dladm_feth_attr_t flinfo;
+
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":R:", feth_lopts,
+ NULL)) != -1) {
+ switch (option) {
+ case 'R':
+ altroot = optarg;
+ break;
+ default:
+ die_opterr(optopt, option, use);
+ }
+ }
+
+ /* get feth name (required last argument) */
+ if (optind != (argc - 1))
+ usage();
+
+ if (!dladm_valid_linkname(argv[optind]))
+ die("invalid link name '%s'", argv[optind]);
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
+ NULL);
+ if (status != DLADM_STATUS_OK)
+ die("feth '%s' not found", argv[optind]);
+
+ if ((status = dladm_feth_info(handle, linkid, &flinfo,
+ flags)) != DLADM_STATUS_OK)
+ die_dlerr(status, "failed to retrieve feth information");
+
+ status = dladm_feth_delete(handle, linkid, flags);
+ if (status != DLADM_STATUS_OK)
+ die_dlerr(status, "feth deletion failed");
+}
+
+static dladm_status_t
+print_feth(show_state_t *state, datalink_id_t linkid)
+{
+ dladm_feth_attr_t flinfo;
+ uint32_t flags;
+ dladm_status_t status;
+ feth_fields_buf_t flbuf;
+ char mstr[ETHERADDRL * 3];
+
+ bzero(&flbuf, sizeof (flbuf));
+ if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
+ flbuf.feth_name, sizeof (flbuf.feth_name)))
+ != DLADM_STATUS_OK)
+ return (status);
+
+ if (!(state->ls_flags & flags))
+ return (DLADM_STATUS_NOTFOUND);
+
+ if ((status = dladm_feth_info(handle, linkid, &flinfo,
+ state->ls_flags)) != DLADM_STATUS_OK)
+ return (status);
+
+ if (flinfo.sna_mac_len > sizeof (flbuf.feth_macaddr))
+ return (DLADM_STATUS_BADVAL);
+
+ (void) strlcpy(flbuf.feth_macaddr,
+ dladm_aggr_macaddr2str(flinfo.sna_mac_addr, mstr),
+ sizeof (flbuf.feth_macaddr));
+
+ ofmt_print(state->ls_ofmt, &flbuf);
+ return (status);
+}
+
+/* ARGSUSED */
+static int
+show_feth(dladm_handle_t dh, datalink_id_t linkid, void *arg)
+{
+ show_state_t* state = arg;
+
+ state->ls_status = print_feth(state, linkid);
+ return (DLADM_WALK_CONTINUE);
+}
+
+static void
+do_show_feth(int argc, char *argv[], const char *use)
+{
+ int option;
+ uint32_t flags = DLADM_OPT_ACTIVE;
+ boolean_t p_arg = B_FALSE;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
+ show_state_t state;
+ dladm_status_t status;
+ boolean_t o_arg = B_FALSE;
+ ofmt_handle_t ofmt;
+ ofmt_status_t oferr;
+ char *all_fields = "link,macaddress";
+ char *fields_str = all_fields;
+ uint_t ofmtflags = 0;
+
+ bzero(&state, sizeof (state));
+
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":pPo:",
+ show_lopts, NULL)) != -1) {
+ switch (option) {
+ case 'p':
+ if (p_arg)
+ die_optdup(option);
+
+ p_arg = B_TRUE;
+ state.ls_parsable = p_arg;
+ break;
+ case 'P':
+ if (flags != DLADM_OPT_ACTIVE)
+ die_optdup(option);
+
+ flags = DLADM_OPT_PERSIST;
+ break;
+ case 'o':
+ o_arg = B_TRUE;
+ fields_str = optarg;
+ break;
+ default:
+ die_opterr(optopt, option, use);
+ break;
+ }
+ }
+
+ if (p_arg && !o_arg)
+ die("-p requires -o");
+
+ if (strcasecmp(fields_str, "all") == 0) {
+ if (p_arg)
+ die("\"-o all\" is invalid with -p");
+ fields_str = all_fields;
+ }
+
+ /* get link name (optional last argument) */
+ if (optind == (argc-1)) {
+ if ((status = dladm_name2info(handle, argv[optind], &linkid,
+ NULL, NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
+ usage();
+ }
+
+ state.ls_flags = flags;
+ state.ls_donefirst = B_FALSE;
+ if (state.ls_parsable)
+ ofmtflags |= OFMT_PARSABLE;
+ oferr = ofmt_open(fields_str, feth_fields, ofmtflags, 0, &ofmt);
+ ofmt_check(oferr, state.ls_parsable, ofmt, die, warn);
+ state.ls_ofmt = ofmt;
+
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_feth, handle, &state,
+ DATALINK_CLASS_FETH, DATALINK_ANY_MEDIATYPE, flags);
+ } else {
+ (void) show_feth(handle, linkid, &state);
+ if (state.ls_status != DLADM_STATUS_OK) {
+ ofmt_close(ofmt);
+ die_dlerr(state.ls_status, "failed to show feth %s",
+ argv[optind]);
+ }
+ }
+ ofmt_close(ofmt);
+}
+
+static void
link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
show_state_t *state)
{
ofmt_handle_t ofmt;
ofmt_status_t oferr;
@@ -8030,11 +8316,12 @@
if (dladm_name2info(handle, links[n], &linkids[n], NULL, &class,
&media) != DLADM_STATUS_OK)
die("invalid link name '%s'", links[n]);
if (class & ~(DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR |
- DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET))
+ DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET |
+ DATALINK_CLASS_FETH))
die("%s %s cannot be bridged",
dladm_class2str(class, pointless), links[n]);
if (media != DL_ETHER && media != DL_100VG &&
media != DL_ETH_CSMA && media != DL_100BT)
die("%s interface %s cannot be bridged",