ifmedia changes:

- Extend the number of available subtypes for Ethernet media by using some
of the ifmedia word's option bits to help denote subtypes. As a result, the
number of possible Ethernet subtype values increases from 31 to 511.

- Use some of those new values to define new media types.

- lacp_compose_key() recgonizes the new Ethernet media types added.
  (Change made as required by a comment in if_media.h)

- New ioctl, SIOGIFXMEDIA, to handle getting the new extended media types.
  SIOCGIFMEDIA is retained for backwards compatibility.

- Changes to ifconfig to allow it to handle the new extended media types.

Submitted by:	mike@karels.net (original), hselasky
Reviewed by:	jfvogel, gnn, hselasky
Approved by:	jfvogel (mentor), gnn (mentor)
Differential Revision: http://reviews.freebsd.org/D1965
This commit is contained in:
Eric Joyner 2015-04-07 21:31:17 +00:00
parent 53deb05c36
commit eb7e25b22f
6 changed files with 201 additions and 14 deletions

View File

@ -109,11 +109,17 @@ media_status(int s)
{
struct ifmediareq ifmr;
int *media_list, i;
int xmedia = 1;
(void) memset(&ifmr, 0, sizeof(ifmr));
(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
/*
* Check if interface supports extended media types.
*/
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0)
xmedia = 0;
if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
/*
* Interface doesn't support SIOC{G,S}IFMEDIA.
*/
@ -130,8 +136,13 @@ media_status(int s)
err(1, "malloc");
ifmr.ifm_ulist = media_list;
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
err(1, "SIOCGIFMEDIA");
if (xmedia) {
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0)
err(1, "SIOCGIFXMEDIA");
} else {
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
err(1, "SIOCGIFMEDIA");
}
printf("\tmedia: ");
print_media_word(ifmr.ifm_current, 1);
@ -194,6 +205,7 @@ ifmedia_getstate(int s)
{
static struct ifmediareq *ifmr = NULL;
int *mwords;
int xmedia = 1;
if (ifmr == NULL) {
ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
@ -213,7 +225,10 @@ ifmedia_getstate(int s)
* the current media type and the top-level type.
*/
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0) {
xmedia = 0;
}
if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
err(1, "SIOCGIFMEDIA");
}
@ -225,8 +240,13 @@ ifmedia_getstate(int s)
err(1, "malloc");
ifmr->ifm_ulist = mwords;
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
err(1, "SIOCGIFMEDIA");
if (xmedia) {
if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)ifmr) < 0)
err(1, "SIOCGIFXMEDIA");
} else {
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
err(1, "SIOCGIFMEDIA");
}
}
return ifmr;

View File

@ -1066,12 +1066,16 @@ lacp_compose_key(struct lacp_port *lp)
case IFM_100_T4:
case IFM_100_VG:
case IFM_100_T2:
case IFM_100_T:
key = IFM_100_TX;
break;
case IFM_1000_SX:
case IFM_1000_LX:
case IFM_1000_CX:
case IFM_1000_T:
case IFM_1000_KX:
case IFM_1000_SGMII:
case IFM_1000_CX_SGMII:
key = IFM_1000_SX;
break;
case IFM_10G_LR:
@ -1081,15 +1085,53 @@ lacp_compose_key(struct lacp_port *lp)
case IFM_10G_TWINAX_LONG:
case IFM_10G_LRM:
case IFM_10G_T:
case IFM_10G_KX4:
case IFM_10G_KR:
case IFM_10G_CR1:
case IFM_10G_ER:
case IFM_10G_SFI:
key = IFM_10G_LR;
break;
case IFM_20G_KR2:
key = IFM_20G_KR2;
break;
case IFM_2500_KX:
case IFM_2500_T:
key = IFM_2500_KX;
break;
case IFM_5000_T:
key = IFM_5000_T;
break;
case IFM_50G_PCIE:
case IFM_50G_CR2:
case IFM_50G_KR2:
key = IFM_50G_PCIE;
break;
case IFM_56G_R4:
key = IFM_56G_R4;
break;
case IFM_25G_PCIE:
case IFM_25G_CR:
case IFM_25G_KR:
case IFM_25G_SR:
key = IFM_25G_PCIE;
break;
case IFM_40G_CR4:
case IFM_40G_SR4:
case IFM_40G_LR4:
case IFM_40G_XLPPI:
case IFM_40G_KR4:
key = IFM_40G_CR4;
break;
case IFM_100G_CR4:
case IFM_100G_SR4:
case IFM_100G_KR4:
case IFM_100G_LR4:
key = IFM_100G_CR4;
break;
default:
key = subtype;
break;
}
/* bit 5..14: (some bits of) if_index of lagg device */
key |= 0x7fe0 & ((sc->sc_ifp->if_index) << 5);

View File

@ -2582,6 +2582,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
case SIOCGIFPSRCADDR:
case SIOCGIFPDSTADDR:
case SIOCGIFMEDIA:
case SIOCGIFXMEDIA:
case SIOCGIFGENERIC:
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);

View File

@ -68,6 +68,7 @@ static struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm,
int flags, int mask);
#ifdef IFMEDIA_DEBUG
#include <net/if_var.h>
int ifmedia_debug = 0;
SYSCTL_INT(_debug, OID_AUTO, ifmedia, CTLFLAG_RW, &ifmedia_debug,
0, "if_media debugging msgs");
@ -192,6 +193,21 @@ ifmedia_set(ifm, target)
#endif
}
/*
* Given a media word, return one suitable for an application
* using the original encoding.
*/
static int
compat_media(int media)
{
if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) {
media &= ~(IFM_ETH_XTYPE|IFM_TMASK);
media |= IFM_OTHER;
}
return (media);
}
/*
* Device-independent media ioctl support function.
*/
@ -271,6 +287,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
* Get list of available media and current media on interface.
*/
case SIOCGIFMEDIA:
case SIOCGIFXMEDIA:
{
struct ifmedia_entry *ep;
int i;
@ -278,8 +295,13 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
if (ifmr->ifm_count < 0)
return (EINVAL);
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
ifm->ifm_cur->ifm_media : IFM_NONE;
if (cmd == SIOCGIFMEDIA) {
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
compat_media(ifm->ifm_cur->ifm_media) : IFM_NONE;
} else {
ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
ifm->ifm_cur->ifm_media : IFM_NONE;
}
ifmr->ifm_mask = ifm->ifm_mask;
ifmr->ifm_status = 0;
(*ifm->ifm_status)(ifp, ifmr);
@ -354,8 +376,7 @@ ifmedia_baudrate(int mword)
int i;
for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) {
if ((mword & (IFM_NMASK|IFM_TMASK)) ==
ifmedia_baudrate_descriptions[i].ifmb_word)
if (IFM_TYPE_MATCH(mword, ifmedia_baudrate_descriptions[i].ifmb_word))
return (ifmedia_baudrate_descriptions[i].ifmb_baudrate);
}
@ -461,7 +482,7 @@ ifmedia_printword(ifmw)
printf("<unknown type>\n");
return;
}
printf(desc->ifmt_string);
printf("%s", desc->ifmt_string);
/* Any mode. */
for (desc = ttos->modes; desc && desc->ifmt_string != NULL; desc++)

View File

@ -118,7 +118,7 @@ uint64_t ifmedia_baudrate(int);
* ---- -------
* 0-4 Media variant
* 5-7 Media type
* 8-15 Type specific options
* 8-15 Type specific options (includes added variant bits on Ethernet)
* 16-18 Mode (for multi-mode devices)
* 19 RFU
* 20-27 Shared (global) options
@ -127,8 +127,18 @@ uint64_t ifmedia_baudrate(int);
/*
* Ethernet
* In order to use more than 31 subtypes, Ethernet uses some of the option
* bits as part of the subtype field. See the options section below for
* relevant definitions
*/
#define IFM_ETHER 0x00000020
#define IFM_ETHER_SUBTYPE(x) (((x) & IFM_TMASK) | \
(((x) & (IFM_ETH_XTYPE >> IFM_ETH_XSHIFT)) << IFM_ETH_XSHIFT))
#define IFM_X(x) IFM_ETHER_SUBTYPE(x) /* internal shorthand */
#define IFM_ETHER_SUBTYPE_SET(x) (IFM_ETHER_SUBTYPE(x) | IFM_ETHER)
#define IFM_ETHER_SUBTYPE_GET(x) ((x) & (IFM_TMASK|IFM_ETH_XTYPE))
#define IFM_ETHER_IS_EXTENDED(x) ((x) & IFM_ETH_XTYPE)
#define IFM_10_T 3 /* 10BaseT - RJ45 */
#define IFM_10_2 4 /* 10Base2 - Thinnet */
#define IFM_10_5 5 /* 10Base5 - AUI */
@ -156,15 +166,49 @@ uint64_t ifmedia_baudrate(int);
#define IFM_40G_CR4 27 /* 40GBase-CR4 */
#define IFM_40G_SR4 28 /* 40GBase-SR4 */
#define IFM_40G_LR4 29 /* 40GBase-LR4 */
#define IFM_1000_KX 30 /* 1000Base-KX backplane */
#define IFM_OTHER 31 /* Other: one of the following */
/* following types are not visible to old binaries using only IFM_TMASK */
#define IFM_10G_KX4 IFM_X(32) /* 10GBase-KX4 backplane */
#define IFM_10G_KR IFM_X(33) /* 10GBase-KR backplane */
#define IFM_10G_CR1 IFM_X(34) /* 10GBase-CR1 Twinax splitter */
#define IFM_20G_KR2 IFM_X(35) /* 20GBase-KR2 backplane */
#define IFM_2500_KX IFM_X(36) /* 2500Base-KX backplane */
#define IFM_2500_T IFM_X(37) /* 2500Base-T - RJ45 (NBaseT) */
#define IFM_5000_T IFM_X(38) /* 5000Base-T - RJ45 (NBaseT) */
#define IFM_50G_PCIE IFM_X(39) /* 50G Ethernet over PCIE */
#define IFM_25G_PCIE IFM_X(40) /* 25G Ethernet over PCIE */
#define IFM_1000_SGMII IFM_X(41) /* 1G media interface */
#define IFM_10G_SFI IFM_X(42) /* 10G media interface */
#define IFM_40G_XLPPI IFM_X(43) /* 40G media interface */
#define IFM_1000_CX_SGMII IFM_X(44) /* 1000Base-CX-SGMII */
#define IFM_40G_KR4 IFM_X(45) /* 40GBase-KR4 */
#define IFM_10G_ER IFM_X(46) /* 10GBase-ER */
#define IFM_100G_CR4 IFM_X(47) /* 100GBase-CR4 */
#define IFM_100G_SR4 IFM_X(48) /* 100GBase-SR4 */
#define IFM_100G_KR4 IFM_X(49) /* 100GBase-KR4 */
#define IFM_100G_LR4 IFM_X(50) /* 100GBase-LR4 */
#define IFM_56G_R4 IFM_X(51) /* 56GBase-R4 */
#define IFM_100_T IFM_X(52) /* 100BaseT - RJ45 */
#define IFM_25G_CR IFM_X(53) /* 25GBase-CR */
#define IFM_25G_KR IFM_X(54) /* 25GBase-KR */
#define IFM_25G_SR IFM_X(55) /* 25GBase-SR */
#define IFM_50G_CR2 IFM_X(56) /* 50GBase-CR2 */
#define IFM_50G_KR2 IFM_X(57) /* 50GBase-KR2 */
/*
* Please update ieee8023ad_lacp.c:lacp_compose_key()
* after adding new Ethernet media types.
*/
/* note 31 is the max! */
/* Note IFM_X(511) is the max! */
/* Ethernet option values; includes bits used for extended variant field */
#define IFM_ETH_MASTER 0x00000100 /* master mode (1000baseT) */
#define IFM_ETH_RXPAUSE 0x00000200 /* receive PAUSE frames */
#define IFM_ETH_TXPAUSE 0x00000400 /* transmit PAUSE frames */
#define IFM_ETH_XTYPE 0x00007800 /* extended media variants */
#define IFM_ETH_XSHIFT 6 /* shift XTYPE next to TMASK */
/*
* Token ring
@ -307,7 +351,10 @@ uint64_t ifmedia_baudrate(int);
* Macros to extract various bits of information from the media word.
*/
#define IFM_TYPE(x) ((x) & IFM_NMASK)
#define IFM_SUBTYPE(x) ((x) & IFM_TMASK)
#define IFM_SUBTYPE(x) \
(IFM_TYPE(x) == IFM_ETHER ? IFM_ETHER_SUBTYPE_GET(x) : ((x) & IFM_TMASK))
#define IFM_TYPE_MATCH(x,y) \
(IFM_TYPE(x) == IFM_TYPE(y) && IFM_SUBTYPE(x) == IFM_SUBTYPE(y))
#define IFM_TYPE_OPTIONS(x) ((x) & IFM_OMASK)
#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT)
#define IFM_OPTIONS(x) ((x) & (IFM_OMASK | IFM_GMASK))
@ -372,6 +419,34 @@ struct ifmedia_description {
{ IFM_40G_CR4, "40Gbase-CR4" }, \
{ IFM_40G_SR4, "40Gbase-SR4" }, \
{ IFM_40G_LR4, "40Gbase-LR4" }, \
{ IFM_1000_KX, "1000Base-KX" }, \
{ IFM_OTHER, "Other" }, \
{ IFM_10G_KX4, "10GBase-KX4" }, \
{ IFM_10G_KR, "10GBase-KR" }, \
{ IFM_10G_CR1, "10GBase-CR1" }, \
{ IFM_20G_KR2, "20GBase-KR2" }, \
{ IFM_2500_KX, "2500Base-KX" }, \
{ IFM_2500_T, "2500Base-T" }, \
{ IFM_5000_T, "5000Base-T" }, \
{ IFM_50G_PCIE, "PCIExpress-50G" }, \
{ IFM_25G_PCIE, "PCIExpress-25G" }, \
{ IFM_1000_SGMII, "1000Base-SGMII" }, \
{ IFM_10G_SFI, "10GBase-SFI" }, \
{ IFM_40G_XLPPI, "40GBase-XLPPI" }, \
{ IFM_1000_CX_SGMII, "1000Base-CX-SGMII" }, \
{ IFM_40G_KR4, "40GBase-KR4" }, \
{ IFM_10G_ER, "10GBase-ER" }, \
{ IFM_100G_CR4, "100GBase-CR4" }, \
{ IFM_100G_SR4, "100GBase-SR4" }, \
{ IFM_100G_KR4, "100GBase-KR4" }, \
{ IFM_100G_LR4, "100GBase-LR4" }, \
{ IFM_56G_R4, "56GBase-R4" }, \
{ IFM_100_T, "100BaseT" }, \
{ IFM_25G_CR, "25GBase-CR" }, \
{ IFM_25G_KR, "25GBase-KR" }, \
{ IFM_25G_SR, "25GBase-SR" }, \
{ IFM_50G_CR2, "50GBase-CR2" }, \
{ IFM_50G_KR2, "50GBase-KR2" }, \
{ 0, NULL }, \
}
@ -673,6 +748,33 @@ struct ifmedia_baudrate {
{ 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_1000_KX, IF_Mbps(1000) }, \
{ IFM_ETHER | IFM_10G_KX4, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_10G_KR, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_10G_CR1, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_20G_KR2, IF_Gbps(20ULL) }, \
{ IFM_ETHER | IFM_2500_KX, IF_Mbps(2500) }, \
{ IFM_ETHER | IFM_2500_T, IF_Mbps(2500) }, \
{ IFM_ETHER | IFM_5000_T, IF_Mbps(5000) }, \
{ IFM_ETHER | IFM_50G_PCIE, IF_Gbps(50ULL) }, \
{ IFM_ETHER | IFM_25G_PCIE, IF_Gbps(25ULL) }, \
{ IFM_ETHER | IFM_1000_SGMII, IF_Mbps(1000) }, \
{ IFM_ETHER | IFM_10G_SFI, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_40G_XLPPI, IF_Gbps(40ULL) }, \
{ IFM_ETHER | IFM_1000_CX_SGMII, IF_Mbps(1000) }, \
{ IFM_ETHER | IFM_40G_KR4, IF_Gbps(40ULL) }, \
{ IFM_ETHER | IFM_10G_ER, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_100G_CR4, IF_Gbps(100ULL) }, \
{ IFM_ETHER | IFM_100G_SR4, IF_Gbps(100ULL) }, \
{ IFM_ETHER | IFM_100G_KR4, IF_Gbps(100ULL) }, \
{ IFM_ETHER | IFM_100G_LR4, IF_Gbps(100ULL) }, \
{ IFM_ETHER | IFM_56G_R4, IF_Gbps(56ULL) }, \
{ IFM_ETHER | IFM_100_T, IF_Mbps(100ULL) }, \
{ IFM_ETHER | IFM_25G_CR, IF_Gbps(25ULL) }, \
{ IFM_ETHER | IFM_25G_KR, IF_Gbps(25ULL) }, \
{ IFM_ETHER | IFM_25G_SR, IF_Gbps(25ULL) }, \
{ IFM_ETHER | IFM_50G_CR2, IF_Gbps(50ULL) }, \
{ IFM_ETHER | IFM_50G_KR2, IF_Gbps(50ULL) }, \
\
{ IFM_TOKEN | IFM_TOK_STP4, IF_Mbps(4) }, \
{ IFM_TOKEN | IFM_TOK_STP16, IF_Mbps(16) }, \

View File

@ -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 SIOCGIFXMEDIA _IOWR('i', 139, struct ifmediareq) /* get net xmedia */
#endif /* !_SYS_SOCKIO_H_ */