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",