Index: sbin/ifconfig/ifmedia.c =================================================================== --- sbin/ifconfig/ifmedia.c +++ sbin/ifconfig/ifmedia.c @@ -90,12 +90,12 @@ static int get_media_mode(int, const char *); static int get_media_options(int, const char *); static int lookup_media_word(struct ifmedia_description *, const char *); -static void print_media_word(int, int); -static void print_media_word_ifconfig(int); +static void print_media(struct ifmed *, int); +static void print_media_ifconfig(struct ifmed *); -static struct ifmedia_description *get_toptype_desc(int); -static struct ifmedia_type_to_subtype *get_toptype_ttos(int); -static struct ifmedia_description *get_subtype_desc(int, +static struct ifmedia_description *get_toptype_desc(struct ifmed *); +static struct ifmedia_type_to_subtype *get_toptype_ttos(struct ifmed *); +static struct ifmedia_description *get_subtype_desc(struct ifmed *, struct ifmedia_type_to_subtype *ttos); #define IFM_OPMODE(x) \ @@ -107,13 +107,14 @@ static void media_status(int s) { - struct ifmediareq ifmr; - int *media_list, i; + struct ifmediareq2 ifmr; + struct ifmed *medias; + int i; - (void) memset(&ifmr, 0, sizeof(ifmr)); (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); + ifmr.ifm_count = 0; - if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { + if (ioctl(s, SIOCGIFMEDIA2, &ifmr) < 0) { /* * Interface doesn't support SIOC{G,S}IFMEDIA. */ @@ -125,20 +126,21 @@ return; } - media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); - if (media_list == NULL) + medias = malloc(ifmr.ifm_count * sizeof(struct ifmed)); + if (medias == NULL) err(1, "malloc"); - ifmr.ifm_ulist = media_list; + ifmr.ifm_entries = medias; - if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) - err(1, "SIOCGIFMEDIA"); + if (ioctl(s, SIOCGIFMEDIA2, &ifmr) < 0) + err(1, "SIOCGIFMEDIA2"); printf("\tmedia: "); - print_media_word(ifmr.ifm_current, 1); - if (ifmr.ifm_active != ifmr.ifm_current) { + print_media(&medias[ifmr.ifm_current], 1); + if (bcmp(&ifmr.ifm_active, &medias[ifmr.ifm_current], + sizeof(struct ifmed)) != 0) { putchar(' '); putchar('('); - print_media_word(ifmr.ifm_active, 0); + print_media(&ifmr.ifm_active, 0); putchar(')'); } @@ -146,7 +148,7 @@ if (ifmr.ifm_status & IFM_AVALID) { printf("\tstatus: "); - switch (IFM_TYPE(ifmr.ifm_active)) { + switch (ifmr.ifm_active.ifm_type) { case IFM_ETHER: case IFM_ATM: if (ifmr.ifm_status & IFM_ACTIVE) @@ -166,7 +168,8 @@ case IFM_IEEE80211: if (ifmr.ifm_status & IFM_ACTIVE) { /* NB: only sta mode associates */ - if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA) + if (IFM_OPMODE(ifmr.ifm_active.ifm_tflags) == + IFM_IEEE80211_STA) printf("associated"); else printf("running"); @@ -181,12 +184,12 @@ printf("\tsupported media:\n"); for (i = 0; i < ifmr.ifm_count; i++) { printf("\t\t"); - print_media_word_ifconfig(media_list[i]); + print_media_ifconfig(&medias[i]); putchar('\n'); } } - free(media_list); + free(medias); } struct ifmediareq * @@ -630,32 +633,34 @@ return (-1); } -static struct ifmedia_description *get_toptype_desc(int ifmw) +static struct ifmedia_description * +get_toptype_desc(struct ifmed *media) { struct ifmedia_description *desc; for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) - if (IFM_TYPE(ifmw) == desc->ifmt_word) + if (media->ifm_type == desc->ifmt_word) break; return desc; } -static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw) +static struct ifmedia_type_to_subtype * +get_toptype_ttos(struct ifmed *media) { struct ifmedia_description *desc; struct ifmedia_type_to_subtype *ttos; for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; desc->ifmt_string != NULL; desc++, ttos++) - if (IFM_TYPE(ifmw) == desc->ifmt_word) + if (media->ifm_type == desc->ifmt_word) break; return ttos; } -static struct ifmedia_description *get_subtype_desc(int ifmw, - struct ifmedia_type_to_subtype *ttos) +static struct ifmedia_description * +get_subtype_desc(struct ifmed *media, struct ifmedia_type_to_subtype *ttos) { int i; struct ifmedia_description *desc; @@ -665,7 +670,7 @@ continue; for (desc = ttos->subtypes[i].desc; desc->ifmt_string != NULL; desc++) { - if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) + if (media->ifm_variant == desc->ifmt_word) return desc; } } @@ -673,8 +678,8 @@ return NULL; } -static struct ifmedia_description *get_mode_desc(int ifmw, - struct ifmedia_type_to_subtype *ttos) +static struct ifmedia_description * +get_mode_desc(struct ifmed *media, struct ifmedia_type_to_subtype *ttos) { int i; struct ifmedia_description *desc; @@ -684,7 +689,7 @@ continue; for (desc = ttos->modes[i].desc; desc->ifmt_string != NULL; desc++) { - if (IFM_MODE(ifmw) == desc->ifmt_word) + if (media->ifm_tflags == desc->ifmt_word) return desc; } } @@ -693,15 +698,15 @@ } static void -print_media_word(int ifmw, int print_toptype) +print_media(struct ifmed *media, int print_toptype) { struct ifmedia_description *desc; struct ifmedia_type_to_subtype *ttos; int seen_option = 0, i; /* Find the top-level interface type. */ - desc = get_toptype_desc(ifmw); - ttos = get_toptype_ttos(ifmw); + desc = get_toptype_desc(media); + ttos = get_toptype_ttos(media); if (desc->ifmt_string == NULL) { printf(""); return; @@ -715,7 +720,7 @@ */ /* Find subtype. */ - desc = get_subtype_desc(ifmw, ttos); + desc = get_subtype_desc(media, ttos); if (desc == NULL) { printf(""); return; @@ -727,7 +732,7 @@ printf("%s", desc->ifmt_string); if (print_toptype) { - desc = get_mode_desc(ifmw, ttos); + desc = get_mode_desc(media, ttos); if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string)) printf(" mode %s", desc->ifmt_string); } @@ -738,7 +743,7 @@ continue; for (desc = ttos->options[i].desc; desc->ifmt_string != NULL; desc++) { - if (ifmw & desc->ifmt_word) { + if (media->ifm_flags & desc->ifmt_word) { if (seen_option == 0) printf(" <"); printf("%s%s", seen_option++ ? "," : "", @@ -748,20 +753,20 @@ } printf("%s", seen_option ? ">" : ""); - if (print_toptype && IFM_INST(ifmw) != 0) - printf(" instance %d", IFM_INST(ifmw)); + if (print_toptype && media->ifm_instance != 0) + printf(" instance %u", media->ifm_instance); } static void -print_media_word_ifconfig(int ifmw) +print_media_ifconfig(struct ifmed *media) { struct ifmedia_description *desc; struct ifmedia_type_to_subtype *ttos; int seen_option = 0, i; /* Find the top-level interface type. */ - desc = get_toptype_desc(ifmw); - ttos = get_toptype_ttos(ifmw); + desc = get_toptype_desc(media); + ttos = get_toptype_ttos(media); if (desc->ifmt_string == NULL) { printf(""); return; @@ -773,7 +778,7 @@ */ /* Find subtype. */ - desc = get_subtype_desc(ifmw, ttos); + desc = get_subtype_desc(media, ttos); if (desc == NULL) { printf(""); return; @@ -781,7 +786,7 @@ printf("media %s", desc->ifmt_string); - desc = get_mode_desc(ifmw, ttos); + desc = get_mode_desc(media, ttos); if (desc != NULL) printf(" mode %s", desc->ifmt_string); @@ -791,7 +796,7 @@ continue; for (desc = ttos->options[i].desc; desc->ifmt_string != NULL; desc++) { - if (ifmw & desc->ifmt_word) { + if (media->ifm_flags & desc->ifmt_word) { if (seen_option == 0) printf(" mediaopt "); printf("%s%s", seen_option++ ? "," : "", @@ -800,8 +805,8 @@ } } - if (IFM_INST(ifmw) != 0) - printf(" instance %d", IFM_INST(ifmw)); + if (media->ifm_instance != 0) + printf(" instance %u", media->ifm_instance); } /********************************************************************** Index: sys/dev/virtio/network/if_vtnet.c =================================================================== --- sys/dev/virtio/network/if_vtnet.c +++ sys/dev/virtio/network/if_vtnet.c @@ -939,6 +939,15 @@ vtnet_ifmedia_sts); ifmedia_add(&sc->vtnet_media, VTNET_MEDIATYPE, 0, NULL); ifmedia_set(&sc->vtnet_media, VTNET_MEDIATYPE); + { + struct ifmed ifm = { + .ifm_type = IFM_ETHER, + .ifm_variant = IFM_VFAST, + }; + + ifmedia_add2(&sc->vtnet_media, &ifm); + ifmedia_set2(&sc->vtnet_media, &ifm); + } /* Read (or generate) the MAC address for the adapter. */ vtnet_get_hwaddr(sc); @@ -1103,6 +1112,7 @@ case SIOCSIFMEDIA: case SIOCGIFMEDIA: + case SIOCGIFMEDIA2: error = ifmedia_ioctl(ifp, ifr, &sc->vtnet_media, cmd); break; Index: sys/net/if_media.h =================================================================== --- sys/net/if_media.h +++ sys/net/if_media.h @@ -38,17 +38,26 @@ #ifndef _NET_IF_MEDIA_H_ #define _NET_IF_MEDIA_H_ -/* - * Prototypes and definitions for BSD/OS-compatible network interface - * media selection. - * - * Where it is safe to do so, this code strays slightly from the BSD/OS - * design. Software which uses the API (device drivers, basically) - * shouldn't notice any difference. - * - * Many thanks to Matt Thomas for providing the information necessary - * to implement this interface. - */ +struct ifmed { + uint32_t ifm_type; /* Ether, 802.11, etc. */ + uint32_t ifm_variant; /* Type-specific variant */ + uint32_t ifm_tflags; /* Type-specific flags */ + uint32_t ifm_flags; /* Common flags */ + uint32_t ifm_instance; /* Instance */ + uint32_t ifm_spare1; + uint32_t ifm_spare2; + uint32_t ifm_spare3; + uint32_t ifm_spare4; +}; + +struct ifmediareq2 { + char ifm_name[IFNAMSIZ]; /* interface name */ + int ifm_status; /* media status */ + int ifm_count; /* entries in array */ + int ifm_current; /* current media idx in array */ + struct ifmed ifm_active; /* active media */ + struct ifmed *ifm_entries; +}; #ifdef _KERNEL @@ -61,6 +70,7 @@ */ typedef int (*ifm_change_cb_t)(struct ifnet *); typedef void (*ifm_stat_cb_t)(struct ifnet *, struct ifmediareq *req); +typedef void (*ifm_stat2_cb_t)(struct ifnet *, struct ifmediareq2 *req); /* * In-kernel representation of a single supported media type. @@ -70,6 +80,7 @@ int ifm_media; /* description of this media attachment */ int ifm_data; /* for driver-specific use */ void *ifm_aux; /* for driver-specific use */ + struct ifmed ifm_media2; }; /* @@ -83,6 +94,7 @@ LIST_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */ ifm_change_cb_t ifm_change; /* media change driver callback */ ifm_stat_cb_t ifm_status; /* media status driver callback */ + ifm_stat2_cb_t ifm_status2; /* media status driver callback */ }; /* Initialize an interface's struct if_media field. */ @@ -94,6 +106,7 @@ /* Add one supported medium to a struct ifmedia. */ void ifmedia_add(struct ifmedia *ifm, int mword, int data, void *aux); +void ifmedia_add2(struct ifmedia *, struct ifmed *); /* Add an array (of ifmedia_entry) media to a struct ifmedia. */ void ifmedia_list_add(struct ifmedia *mp, struct ifmedia_entry *lp, @@ -101,12 +114,12 @@ /* Set default media type on initialization. */ void ifmedia_set(struct ifmedia *ifm, int mword); +void ifmedia_set2(struct ifmedia *, struct ifmed *); /* Common ioctl function for getting/setting media, called by driver. */ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, struct ifmedia *ifm, u_long cmd); - /* Compute baudrate for a given media. */ uint64_t ifmedia_baudrate(int); @@ -156,6 +169,7 @@ #define IFM_40G_CR4 27 /* 40GBase-CR4 */ #define IFM_40G_SR4 28 /* 40GBase-SR4 */ #define IFM_40G_LR4 29 /* 40GBase-LR4 */ +#define IFM_VFAST 42 /* experimental */ /* * Please update ieee8023ad_lacp.c:lacp_compose_key() * after adding new Ethernet media types. @@ -324,6 +338,12 @@ (((mode) << IFM_MSHIFT) & IFM_MMASK) /* + * Maximum values for variant in media word. + */ +#define IFM_VARIANT_MIN 3 +#define IFM_VARIANT_MAX ((1 << 5) - 1) + +/* * NetBSD extension not defined in the BSDI API. This is used in various * places to get the canonical description for a given type/subtype. * @@ -372,6 +392,7 @@ { IFM_40G_CR4, "40Gbase-CR4" }, \ { IFM_40G_SR4, "40Gbase-SR4" }, \ { IFM_40G_LR4, "40Gbase-LR4" }, \ + { IFM_VFAST, "V.fast" }, \ { 0, NULL }, \ } @@ -673,6 +694,7 @@ { IFM_ETHER | IFM_40G_CR4, IF_Gbps(40ULL) }, \ { IFM_ETHER | IFM_40G_SR4, IF_Gbps(40ULL) }, \ { IFM_ETHER | IFM_40G_LR4, IF_Gbps(40ULL) }, \ + { IFM_ETHER | IFM_VFAST, IF_Gbps(42ULL) }, \ \ { IFM_TOKEN | IFM_TOK_STP4, IF_Mbps(4) }, \ { IFM_TOKEN | IFM_TOK_STP16, IF_Mbps(16) }, \ Index: sys/net/if_media.c =================================================================== --- sys/net/if_media.c +++ sys/net/if_media.c @@ -66,6 +66,8 @@ static struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm, int flags, int mask); +static int ifmed2word(struct ifmed *); +static void word2ifmed(struct ifmed *, int); #ifdef IFMEDIA_DEBUG int ifmedia_debug = 0; @@ -138,6 +140,32 @@ entry->ifm_data = data; entry->ifm_aux = aux; + /* Fill in new style info. */ + word2ifmed(&entry->ifm_media2, mword); + + LIST_INSERT_HEAD(&ifm->ifm_list, entry, ifm_list); +} + +/* + * Add a media configuration to the list of supported media + * for a specific interface instance (new API). + */ +void +ifmedia_add2(struct ifmedia *ifm, struct ifmed *med) +{ + struct ifmedia_entry *entry; + + entry = malloc(sizeof(*entry), M_IFADDR, M_NOWAIT); + if (entry == NULL) + panic("ifmedia_add2: can't malloc entry"); + + /* Thrash old fields. If driver uses new API, it doesn't access them. */ + entry->ifm_media = 0xdeadc0de; + entry->ifm_data = 0; + entry->ifm_aux = NULL; + + entry->ifm_media2 = *med; + LIST_INSERT_HEAD(&ifm->ifm_list, entry, ifm_list); } @@ -193,6 +221,24 @@ } /* + * Set the default active media using new ifmed. + */ +void +ifmedia_set2(struct ifmedia *ifm, struct ifmed *set) +{ + struct ifmedia_entry *ent; + + LIST_FOREACH(ent, &ifm->ifm_list, ifm_list) + if (ent->ifm_media2.ifm_type == set->ifm_type && + ent->ifm_media2.ifm_variant == set->ifm_variant) { + ifm->ifm_cur = ent; + break; + } + + KASSERT(ent, ("%s: not match", __func__)); +} + +/* * Device-independent media ioctl support function. */ int @@ -279,7 +325,7 @@ return (EINVAL); ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ? - ifm->ifm_cur->ifm_media : IFM_NONE; + ifmed2word(&ifm->ifm_cur->ifm_media2) : IFM_NONE; ifmr->ifm_mask = ifm->ifm_mask; ifmr->ifm_status = 0; (*ifm->ifm_status)(ifp, ifmr); @@ -293,8 +339,11 @@ i = 0; LIST_FOREACH(ep, &ifm->ifm_list, ifm_list) if (i++ < ifmr->ifm_count) { - error = copyout(&ep->ifm_media, - ifmr->ifm_ulist + i - 1, sizeof(int)); + int mword; + + mword = ifmed2word(&ep->ifm_media2); + error = copyout(&mword, ifmr->ifm_ulist + i - 1, + sizeof(int)); if (error) break; } @@ -304,6 +353,50 @@ break; } + case SIOCGIFMEDIA2: + { + struct ifmediareq2 *ifmr = (struct ifmediareq2 *) ifr; + struct ifmedia_entry *ep; + int i; + + if (ifmr->ifm_count < 0) + return (EINVAL); + + ifmr->ifm_active = ifm->ifm_cur->ifm_media2; + ifmr->ifm_status = 0; + if (ifm->ifm_status2) + ifm->ifm_status2(ifp, ifmr); + else { + struct ifmediareq oifmr; + + ifm->ifm_status(ifp, &oifmr); + ifmr->ifm_status = oifmr.ifm_status; + word2ifmed(&ifmr->ifm_active, oifmr.ifm_active); + } + + /* + * If there are more interfaces on the list, count + * them. This allows the caller to set ifmr->ifm_count + * to 0 on the first call to know how much space to + * allocate. + */ + i = 0; + LIST_FOREACH(ep, &ifm->ifm_list, ifm_list) + if (i++ < ifmr->ifm_count) { + error = copyout(&ep->ifm_media2, + ifmr->ifm_entries + i - 1, + sizeof(struct ifmed)); + if (error) + break; + if (ifm->ifm_cur == ep) + ifmr->ifm_current = i - 1; + } + if (error == 0 && i > ifmr->ifm_count) + error = ifmr->ifm_count ? E2BIG : 0; + ifmr->ifm_count = i; + break; + } + default: return (EINVAL); } @@ -362,6 +455,38 @@ /* Not known. */ return (0); } + +/* + * Compat: try to produce old media word from struct ifmed. + */ +static int +ifmed2word(struct ifmed *media) +{ + uint32_t variant; + + /* XXXGL: for now only variant may not fit into old API. */ + variant = (media->ifm_type == IFM_ETHER && + (media->ifm_variant < IFM_VARIANT_MIN || + media->ifm_variant > IFM_VARIANT_MAX)) ? + IFM_UNKNOWN : media->ifm_variant; + + return (IFM_MAKEWORD(media->ifm_type, variant, + media->ifm_flags | media->ifm_tflags, media->ifm_instance)); +}; + +/* + * Compat: produce struct ifmed using old media word. + */ +static void +word2ifmed(struct ifmed *media, int mword) +{ + + media->ifm_type = IFM_TYPE(mword); + media->ifm_variant = IFM_SUBTYPE(mword); + media->ifm_tflags = IFM_TYPE_OPTIONS(mword); + media->ifm_flags = IFM_OPTIONS(mword); + media->ifm_instance = IFM_INST(mword); +} #ifdef IFMEDIA_DEBUG struct ifmedia_description ifm_type_descriptions[] = Index: sys/sys/sockio.h =================================================================== --- sys/sys/sockio.h +++ sys/sys/sockio.h @@ -128,5 +128,6 @@ #define SIOCGIFGROUP _IOWR('i', 136, struct ifgroupreq) /* get ifgroups */ #define SIOCDIFGROUP _IOW('i', 137, struct ifgroupreq) /* delete ifgroup */ #define SIOCGIFGMEMB _IOWR('i', 138, struct ifgroupreq) /* get members */ +#define SIOCGIFMEDIA2 _IOWR('i', 139, struct ifmediareq2) /* get net media */ #endif /* !_SYS_SOCKIO_H_ */