Loading...
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
/*
 * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
/*
 * Copyright (c) 1982, 1986, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	From: @(#)if.h	8.1 (Berkeley) 6/10/93
 * $FreeBSD: src/sys/net/if_var.h,v 1.18.2.7 2001/07/24 19:10:18 brooks Exp $
 */

#ifndef	_NET_IF_VAR_H_
#define	_NET_IF_VAR_H_

#include <sys/appleapiopts.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>		/* get TAILQ macros */
#ifdef KERNEL_PRIVATE
#include <kern/locks.h>
#endif /* KERNEL_PRIVATE */
#ifdef PRIVATE
#include <net/route.h>
#endif
#ifdef BSD_KERN_PRIVATE
#include <sys/eventhandler.h>
#endif

#ifdef KERNEL
#include <net/kpi_interface.h>
#endif /* KERNEL */

#ifdef __APPLE__
#define APPLE_IF_FAM_LOOPBACK  1
#define APPLE_IF_FAM_ETHERNET  2
#define APPLE_IF_FAM_SLIP      3
#define APPLE_IF_FAM_TUN       4
#define APPLE_IF_FAM_VLAN      5
#define APPLE_IF_FAM_PPP       6
#define APPLE_IF_FAM_PVC       7
#define APPLE_IF_FAM_DISC      8
#define APPLE_IF_FAM_MDECAP    9
#define APPLE_IF_FAM_GIF       10
#define APPLE_IF_FAM_FAITH     11	/* deprecated */
#define APPLE_IF_FAM_STF       12
#define APPLE_IF_FAM_FIREWIRE  13
#define APPLE_IF_FAM_BOND      14
#endif /* __APPLE__ */

/*
 * 72 was chosen below because it is the size of a TCP/IP
 * header (40) + the minimum mss (32).
 */
#define	IF_MINMTU	72
#define	IF_MAXMTU	65535

/*
 * Structures defining a network interface, providing a packet
 * transport mechanism (ala level 0 of the PUP protocols).
 *
 * Each interface accepts output datagrams of a specified maximum
 * length, and provides higher level routines with input datagrams
 * received from its medium.
 *
 * Output occurs when the routine if_output is called, with three parameters:
 *	(*ifp->if_output)(ifp, m, dst, rt)
 * Here m is the mbuf chain to be sent and dst is the destination address.
 * The output routine encapsulates the supplied datagram if necessary,
 * and then transmits it on its medium.
 *
 * On input, each interface unwraps the data received by it, and either
 * places it on the input queue of a internetwork datagram routine
 * and posts the associated software interrupt, or passes the datagram to a raw
 * packet input routine.
 *
 * Routines exist for locating interfaces by their addresses
 * or for locating a interface on a certain network, as well as more general
 * routing and gateway routines maintaining information used to locate
 * interfaces.  These routines live in the files if.c and route.c
 */

#define	IFNAMSIZ	16

/* This belongs up in socket.h or socketvar.h, depending on how far the
 *   event bubbles up.
 */

struct net_event_data {
	u_int32_t	if_family;
	u_int32_t	if_unit;
	char		if_name[IFNAMSIZ];
};

#if defined(__LP64__)
#include <sys/_types/_timeval32.h>
#define IF_DATA_TIMEVAL timeval32
#else
#define IF_DATA_TIMEVAL timeval
#endif

#pragma pack(4)

/*
 * Structure describing information about an interface
 * which may be of interest to management entities.
 */
struct if_data {
	/* generic interface information */
	u_char		ifi_type;	/* ethernet, tokenring, etc */
	u_char		ifi_typelen;	/* Length of frame type id */
	u_char		ifi_physical;	/* e.g., AUI, Thinnet, 10base-T, etc */
	u_char		ifi_addrlen;	/* media address length */
	u_char		ifi_hdrlen;	/* media header length */
	u_char		ifi_recvquota;	/* polling quota for receive intrs */
	u_char		ifi_xmitquota;	/* polling quota for xmit intrs */
	u_char		ifi_unused1;	/* for future use */
	u_int32_t	ifi_mtu;	/* maximum transmission unit */
	u_int32_t	ifi_metric;	/* routing metric (external only) */
	u_int32_t	ifi_baudrate;	/* linespeed */
	/* volatile statistics */
	u_int32_t	ifi_ipackets;	/* packets received on interface */
	u_int32_t	ifi_ierrors;	/* input errors on interface */
	u_int32_t	ifi_opackets;	/* packets sent on interface */
	u_int32_t	ifi_oerrors;	/* output errors on interface */
	u_int32_t	ifi_collisions;	/* collisions on csma interfaces */
	u_int32_t	ifi_ibytes;	/* total number of octets received */
	u_int32_t	ifi_obytes;	/* total number of octets sent */
	u_int32_t	ifi_imcasts;	/* packets received via multicast */
	u_int32_t	ifi_omcasts;	/* packets sent via multicast */
	u_int32_t	ifi_iqdrops;	/* dropped on input, this interface */
	u_int32_t	ifi_noproto;	/* destined for unsupported protocol */
	u_int32_t	ifi_recvtiming;	/* usec spent receiving when timing */
	u_int32_t	ifi_xmittiming;	/* usec spent xmitting when timing */
	struct IF_DATA_TIMEVAL ifi_lastchange;	/* time of last administrative change */
	u_int32_t	ifi_unused2;	/* used to be the default_proto */
	u_int32_t	ifi_hwassist;	/* HW offload capabilities */
	u_int32_t	ifi_reserved1;	/* for future use */
	u_int32_t	ifi_reserved2;	/* for future use */
};

/*
 * Structure describing information about an interface
 * which may be of interest to management entities.
 */
struct if_data64 {
	/* generic interface information */
	u_char		ifi_type;		/* ethernet, tokenring, etc */
	u_char		ifi_typelen;		/* Length of frame type id */
	u_char		ifi_physical;		/* e.g., AUI, Thinnet, 10base-T, etc */
	u_char		ifi_addrlen;		/* media address length */
	u_char		ifi_hdrlen;		/* media header length */
	u_char		ifi_recvquota;		/* polling quota for receive intrs */
	u_char		ifi_xmitquota;		/* polling quota for xmit intrs */
	u_char		ifi_unused1;		/* for future use */
	u_int32_t	ifi_mtu;		/* maximum transmission unit */
	u_int32_t	ifi_metric;		/* routing metric (external only) */
	u_int64_t	ifi_baudrate;		/* linespeed */
	/* volatile statistics */
	u_int64_t	ifi_ipackets;		/* packets received on interface */
	u_int64_t	ifi_ierrors;		/* input errors on interface */
	u_int64_t	ifi_opackets;		/* packets sent on interface */
	u_int64_t	ifi_oerrors;		/* output errors on interface */
	u_int64_t	ifi_collisions;		/* collisions on csma interfaces */
	u_int64_t	ifi_ibytes;		/* total number of octets received */
	u_int64_t	ifi_obytes;		/* total number of octets sent */
	u_int64_t	ifi_imcasts;		/* packets received via multicast */
	u_int64_t	ifi_omcasts;		/* packets sent via multicast */
	u_int64_t	ifi_iqdrops;		/* dropped on input, this interface */
	u_int64_t	ifi_noproto;		/* destined for unsupported protocol */
	u_int32_t	ifi_recvtiming;		/* usec spent receiving when timing */
	u_int32_t	ifi_xmittiming;		/* usec spent xmitting when timing */
	struct IF_DATA_TIMEVAL ifi_lastchange;	/* time of last administrative change */
};

#ifdef PRIVATE
struct if_traffic_class {
	u_int64_t		ifi_ibepackets;	/* TC_BE packets received on interface */
	u_int64_t		ifi_ibebytes;	/* TC_BE bytes received on interface */
	u_int64_t		ifi_obepackets;	/* TC_BE packet sent on interface */
	u_int64_t		ifi_obebytes;	/* TC_BE bytes sent on interface */
	u_int64_t		ifi_ibkpackets;	/* TC_BK packets received on interface */
	u_int64_t		ifi_ibkbytes;	/* TC_BK bytes received on interface */
	u_int64_t		ifi_obkpackets;	/* TC_BK packet sent on interface */
	u_int64_t		ifi_obkbytes;	/* TC_BK bytes sent on interface */
	u_int64_t		ifi_ivipackets;	/* TC_VI packets received on interface */
	u_int64_t		ifi_ivibytes;	/* TC_VI bytes received on interface */
	u_int64_t		ifi_ovipackets;	/* TC_VI packets sent on interface */
	u_int64_t		ifi_ovibytes;	/* TC_VI bytes sent on interface */
	u_int64_t		ifi_ivopackets;	/* TC_VO packets received on interface */
	u_int64_t		ifi_ivobytes;	/* TC_VO bytes received on interface */
	u_int64_t		ifi_ovopackets;	/* TC_VO packets sent on interface */
	u_int64_t		ifi_ovobytes;	/* TC_VO bytes sent on interface */
	u_int64_t		ifi_ipvpackets;	/* TC priv packets received on interface */
	u_int64_t		ifi_ipvbytes;	/* TC priv bytes received on interface */
	u_int64_t		ifi_opvpackets;	/* TC priv packets sent on interface */
	u_int64_t		ifi_opvbytes;	/* TC priv bytes sent on interface */
};

struct if_data_extended {
	u_int64_t	ifi_alignerrs;	/* unaligned (32-bit) input pkts */
	u_int64_t	ifi_dt_bytes;	/* Data threshold counter */
	u_int64_t	ifi_fpackets;	/* forwarded packets on interface */
	u_int64_t	ifi_fbytes;	/* forwarded bytes on interface */
	u_int64_t	reserved[12];	/* for future */
};

struct if_packet_stats {
	/* TCP */
	u_int64_t		ifi_tcp_badformat;
	u_int64_t		ifi_tcp_unspecv6;
	u_int64_t		ifi_tcp_synfin;
	u_int64_t		ifi_tcp_badformatipsec;
	u_int64_t		ifi_tcp_noconnnolist;
	u_int64_t		ifi_tcp_noconnlist;
	u_int64_t		ifi_tcp_listbadsyn;
	u_int64_t		ifi_tcp_icmp6unreach;
	u_int64_t		ifi_tcp_deprecate6;
	u_int64_t		ifi_tcp_rstinsynrcv;
	u_int64_t		ifi_tcp_ooopacket;
	u_int64_t		ifi_tcp_dospacket;
	u_int64_t		ifi_tcp_cleanup;
	u_int64_t		ifi_tcp_synwindow;
	u_int64_t		reserved[6];
	/* UDP */
	u_int64_t		ifi_udp_port_unreach;
	u_int64_t		ifi_udp_faithprefix;
	u_int64_t		ifi_udp_port0;
	u_int64_t		ifi_udp_badlength;
	u_int64_t		ifi_udp_badchksum;
	u_int64_t		ifi_udp_badmcast;
	u_int64_t		ifi_udp_cleanup;
	u_int64_t		ifi_udp_badipsec;
	u_int64_t		_reserved[4];
};

struct if_description {
	u_int32_t	ifd_maxlen;	/* must be IF_DESCSIZE */
	u_int32_t	ifd_len;	/* actual ifd_desc length */
	u_int8_t	*ifd_desc;	/* ptr to desc buffer */
};

struct if_bandwidths {
	u_int64_t	eff_bw;		/* effective bandwidth */
	u_int64_t	max_bw;		/* maximum theoretical bandwidth */
};

struct if_latencies {
	u_int64_t	eff_lt;		/* effective latency */
	u_int64_t	max_lt;		/* maximum theoretical latency */
};

struct if_rxpoll_stats {
	u_int32_t	ifi_poll_off_req;	/* total # of POLL_OFF reqs */
	u_int32_t	ifi_poll_off_err;	/* total # of POLL_OFF errors */
	u_int32_t	ifi_poll_on_req;	/* total # of POLL_ON reqs */
	u_int32_t	ifi_poll_on_err;	/* total # of POLL_ON errors */

	u_int32_t	ifi_poll_wakeups_avg;	/* avg # of wakeup reqs */
	u_int32_t	ifi_poll_wakeups_lowat;	/* wakeups low watermark */
	u_int32_t	ifi_poll_wakeups_hiwat;	/* wakeups high watermark */

	u_int64_t	ifi_poll_packets;	/* total # of polled packets */
	u_int32_t	ifi_poll_packets_avg;	/* average polled packets */
	u_int32_t	ifi_poll_packets_min;	/* smallest polled packets */
	u_int32_t	ifi_poll_packets_max;	/* largest polled packets */
	u_int32_t	ifi_poll_packets_lowat;	/* packets low watermark */
	u_int32_t	ifi_poll_packets_hiwat;	/* packets high watermark */

	u_int64_t	ifi_poll_bytes;		/* total # of polled bytes */
	u_int32_t	ifi_poll_bytes_avg;	/* average polled bytes */
	u_int32_t	ifi_poll_bytes_min;	/* smallest polled bytes */
	u_int32_t	ifi_poll_bytes_max;	/* largest polled bytes */
	u_int32_t	ifi_poll_bytes_lowat;	/* bytes low watermark */
	u_int32_t	ifi_poll_bytes_hiwat;	/* bytes high watermark */

	u_int32_t	ifi_poll_packets_limit;	/* max packets per poll call */
	u_int64_t	ifi_poll_interval_time;	/* poll interval (nsec) */
};

struct if_tcp_ecn_perf_stat {
	u_int64_t total_txpkts;
	u_int64_t total_rxmitpkts;
	u_int64_t total_rxpkts;
	u_int64_t total_oopkts;
	u_int64_t total_reorderpkts;
	u_int64_t rtt_avg;
	u_int64_t rtt_var;
	u_int64_t sack_episodes;
	u_int64_t rxmit_drop;
	u_int64_t rst_drop;
	u_int64_t oo_percent;
	u_int64_t reorder_percent;
	u_int64_t rxmit_percent;
};

struct if_tcp_ecn_stat {
	u_int64_t timestamp;
	u_int64_t ecn_client_setup;
	u_int64_t ecn_server_setup;
	u_int64_t ecn_client_success;
	u_int64_t ecn_server_success;
	u_int64_t ecn_peer_nosupport;
	u_int64_t ecn_syn_lost;
	u_int64_t ecn_synack_lost;
	u_int64_t ecn_recv_ce;
	u_int64_t ecn_recv_ece;
	u_int64_t ecn_conn_recv_ce;
	u_int64_t ecn_conn_recv_ece;
	u_int64_t ecn_conn_plnoce;
	u_int64_t ecn_conn_plce;
	u_int64_t ecn_conn_noplce;
	u_int64_t ecn_fallback_synloss;
	u_int64_t ecn_fallback_reorder;
	u_int64_t ecn_fallback_ce;
	u_int64_t ecn_off_conn;
	u_int64_t ecn_total_conn;
	u_int64_t ecn_fallback_droprst;
	u_int64_t ecn_fallback_droprxmt;
	u_int64_t ecn_fallback_synrst;
	struct if_tcp_ecn_perf_stat ecn_on;
	struct if_tcp_ecn_perf_stat ecn_off;
};

struct if_lim_perf_stat {
	u_int64_t lim_dl_max_bandwidth;	/* bits per second */
	u_int64_t lim_ul_max_bandwidth;	/* bits per second */
	u_int64_t lim_total_txpkts;	/* Total transmit packets, count */
	u_int64_t lim_total_rxpkts;	/* Total receive packets, count */
	u_int64_t lim_total_retxpkts;	/* Total retransmit packets */
	u_int64_t lim_packet_loss_percent; /* Packet loss rate */
	u_int64_t lim_total_oopkts;	/* Total out-of-order packets */
	u_int64_t lim_packet_ooo_percent; /* Out-of-order packet rate */
	u_int64_t lim_rtt_variance;	/* RTT variance, milliseconds */
	u_int64_t lim_rtt_average;	/* RTT average, milliseconds */
	u_int64_t lim_rtt_min;		/* RTT minimum, milliseconds */
	u_int64_t lim_conn_timeouts;	/* connection timeouts */
	u_int64_t lim_conn_attempts;	/* connection attempts */
	u_int64_t lim_conn_timeout_percent; /* Rate of connection timeouts */
	u_int64_t lim_bk_txpkts;	/* Transmit packets with BK service class, that use delay based algorithms */
	u_int64_t lim_dl_detected:1,	/* Low internet */
		  lim_ul_detected:1;
};

#define IF_VAR_H_HAS_IFNET_STATS_PER_FLOW 1
struct ifnet_stats_per_flow {
	u_int64_t bk_txpackets;
	u_int64_t txpackets;
	u_int64_t rxpackets;
	u_int32_t txretransmitbytes;
	u_int32_t rxoutoforderbytes;
	u_int32_t rxmitpkts;
	u_int32_t rcvoopack;
	u_int32_t pawsdrop;
	u_int32_t sack_recovery_episodes;
	u_int32_t reordered_pkts;
	u_int32_t dsack_sent;
	u_int32_t dsack_recvd;
	u_int32_t srtt;
	u_int32_t rttupdated;
	u_int32_t rttvar;
	u_int32_t rttmin;
	u_int32_t bw_sndbw_max;
	u_int32_t bw_rcvbw_max;
	u_int32_t ecn_recv_ece;
	u_int32_t ecn_recv_ce;
	u_int16_t ecn_flags;
	u_int16_t ipv4:1,
	    local:1,
	    connreset:1,
	    conntimeout:1,
	    rxmit_drop:1,
	    ecn_fallback_synloss:1,
	    ecn_fallback_droprst:1,
	    ecn_fallback_droprxmt:1,
	    ecn_fallback_ce:1,
	    ecn_fallback_reorder:1;
};

/*
 * Interface link status report -- includes statistics related to
 * the link layer technology sent by the driver. The driver will monitor
 * these statistics over an interval (3-4 secs) and will generate a report
 * to the network stack. This will give first-hand information about the
 * status of the first hop of the network path. The version and
 * length values should be correct for the data to be processed correctly.
 * The definitions are different for different kind of interfaces like
 * Wifi, Cellular etc,.
 */
#define IF_CELLULAR_STATUS_REPORT_VERSION_1	1
#define IF_WIFI_STATUS_REPORT_VERSION_1		1
#define IF_CELLULAR_STATUS_REPORT_CURRENT_VERSION	\
					IF_CELLULAR_STATUS_REPORT_VERSION_1
#define IF_WIFI_STATUS_REPORT_CURRENT_VERSION	IF_WIFI_STATUS_REPORT_VERSION_1
/*
 * For cellular interface --
 * There is no way to share common headers between the Baseband and
 * the kernel. Any changes to this structure will need to be communicated
 * to the Baseband team. It is better to use reserved space instead of
 * changing the size or existing fields in the structure.
 */
struct if_cellular_status_v1 {
	u_int32_t valid_bitmask; /* indicates which fields are valid */
#define IF_CELL_LINK_QUALITY_METRIC_VALID	0x1
#define IF_CELL_UL_EFFECTIVE_BANDWIDTH_VALID	0x2
#define IF_CELL_UL_MAX_BANDWIDTH_VALID		0x4
#define IF_CELL_UL_MIN_LATENCY_VALID		0x8
#define IF_CELL_UL_EFFECTIVE_LATENCY_VALID	0x10
#define IF_CELL_UL_MAX_LATENCY_VALID		0x20
#define IF_CELL_UL_RETXT_LEVEL_VALID		0x40
#define IF_CELL_UL_BYTES_LOST_VALID		0x80
#define IF_CELL_UL_MIN_QUEUE_SIZE_VALID		0x100
#define IF_CELL_UL_AVG_QUEUE_SIZE_VALID		0x200
#define IF_CELL_UL_MAX_QUEUE_SIZE_VALID		0x400
#define IF_CELL_DL_EFFECTIVE_BANDWIDTH_VALID	0x800
#define IF_CELL_DL_MAX_BANDWIDTH_VALID		0x1000
#define IF_CELL_CONFIG_INACTIVITY_TIME_VALID	0x2000
#define IF_CELL_CONFIG_BACKOFF_TIME_VALID	0x4000
#define	IF_CELL_UL_MSS_RECOMMENDED_VALID	0x8000

	u_int32_t link_quality_metric;
	u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on current activity (bps) */
	u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth (bps) */
	u_int32_t ul_min_latency; /* min expected uplink latency for first hop (ms) */
	u_int32_t ul_effective_latency; /* current expected uplink latency for first hop (ms) */
	u_int32_t ul_max_latency; /* max expected uplink latency first hop (ms) */
	u_int32_t ul_retxt_level; /* Retransmission metric */
#define IF_CELL_UL_RETXT_LEVEL_NONE	1
#define IF_CELL_UL_RETXT_LEVEL_LOW	2
#define IF_CELL_UL_RETXT_LEVEL_MEDIUM	3
#define IF_CELL_UL_RETXT_LEVEL_HIGH	4
	u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 format */
	u_int32_t ul_min_queue_size; /* minimum bytes in queue */
	u_int32_t ul_avg_queue_size; /* average bytes in queue */
	u_int32_t ul_max_queue_size; /* maximum bytes in queue */
	u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based on current activity (bps) */
	u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth (bps) */
	u_int32_t config_inactivity_time; /* ms */
	u_int32_t config_backoff_time; /* new connections backoff time in ms */
#define	IF_CELL_UL_MSS_RECOMMENDED_NONE	0x0 /* Use default */
#define	IF_CELL_UL_MSS_RECOMMENDED_MEDIUM 0x1 /* 1200 byte MSS */
#define	IF_CELL_UL_MSS_RECOMMENDED_LOW	0x2 /* 512 byte MSS */
	u_int16_t mss_recommended;
	u_int16_t reserved_1;
	u_int32_t reserved_2;
	u_int64_t reserved_3;
	u_int64_t reserved_4;
	u_int64_t reserved_5;
	u_int64_t reserved_6;
} __attribute__((packed));

struct if_cellular_status {
	union {
		struct if_cellular_status_v1 if_status_v1;
	} if_cell_u;
};

/*
 * These statistics will be provided by the Wifi driver periodically.
 * After sending each report, the driver should start computing again
 * for the next report duration so that the values represent the link
 * status for one report duration.
 */

struct if_wifi_status_v1 {
	u_int32_t valid_bitmask;
#define IF_WIFI_LINK_QUALITY_METRIC_VALID	0x1
#define IF_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID	0x2
#define IF_WIFI_UL_MAX_BANDWIDTH_VALID		0x4
#define IF_WIFI_UL_MIN_LATENCY_VALID		0x8
#define IF_WIFI_UL_EFFECTIVE_LATENCY_VALID	0x10
#define IF_WIFI_UL_MAX_LATENCY_VALID		0x20
#define IF_WIFI_UL_RETXT_LEVEL_VALID		0x40
#define IF_WIFI_UL_ERROR_RATE_VALID		0x80
#define IF_WIFI_UL_BYTES_LOST_VALID		0x100
#define IF_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID	0x200
#define IF_WIFI_DL_MAX_BANDWIDTH_VALID		0x400
#define IF_WIFI_DL_MIN_LATENCY_VALID		0x800
#define IF_WIFI_DL_EFFECTIVE_LATENCY_VALID	0x1000
#define IF_WIFI_DL_MAX_LATENCY_VALID		0x2000
#define IF_WIFI_DL_ERROR_RATE_VALID		0x4000
#define IF_WIFI_CONFIG_FREQUENCY_VALID		0x8000
#define IF_WIFI_CONFIG_MULTICAST_RATE_VALID	0x10000
#define IF_WIFI_CONFIG_SCAN_COUNT_VALID		0x20000
#define IF_WIFI_CONFIG_SCAN_DURATION_VALID	0x40000
	u_int32_t link_quality_metric; /* link quality metric */
	u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on current activity (bps) */
	u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth (bps) */
	u_int32_t ul_min_latency; /* min expected uplink latency for first hop (ms) */
	u_int32_t ul_effective_latency; /* current expected uplink latency for first hop (ms) */
	u_int32_t ul_max_latency; /* max expected uplink latency for first hop (ms) */
	u_int32_t ul_retxt_level; /* Retransmission metric */
#define IF_WIFI_UL_RETXT_LEVEL_NONE	1
#define IF_WIFI_UL_RETXT_LEVEL_LOW	2
#define IF_WIFI_UL_RETXT_LEVEL_MEDIUM	3
#define IF_WIFI_UL_RETXT_LEVEL_HIGH	4
	u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 format */
	u_int32_t ul_error_rate; /* % of bytes dropped on uplink after many retransmissions in Q10 format */
	u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based on current activity (bps) */
	u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth (bps) */
	/*
	 * The download latency values indicate the time AP may have to wait for the
	 * driver to receive the packet. These values give the range of expected latency
	 * mainly due to co-existence events and channel hopping where the interface
	 * becomes unavailable.
	 */
	u_int32_t dl_min_latency; /* min expected latency for first hop in ms */
	u_int32_t dl_effective_latency; /* current expected latency for first hop in ms */
	u_int32_t dl_max_latency; /* max expected latency for first hop in ms */
	u_int32_t dl_error_rate; /* % of CRC or other errors in Q10 format */
	u_int32_t config_frequency; /* 2.4 or 5 GHz */
#define IF_WIFI_CONFIG_FREQUENCY_2_4_GHZ	1
#define IF_WIFI_CONFIG_FREQUENCY_5_0_GHZ	2
	u_int32_t config_multicast_rate; /* bps */
	u_int32_t scan_count; /* scan count during the previous period */
	u_int32_t scan_duration; /* scan duration in ms */
	u_int64_t reserved_1;
	u_int64_t reserved_2;
	u_int64_t reserved_3;
	u_int64_t reserved_4;
} __attribute__((packed));

struct if_wifi_status {
	union {
		struct if_wifi_status_v1 if_status_v1;
	} if_wifi_u;
};

struct if_link_status {
	u_int32_t	ifsr_version;	/* version of this report */
	u_int32_t	ifsr_len;	/* length of the following struct */
	union {
		struct if_cellular_status ifsr_cell;
		struct if_wifi_status ifsr_wifi;
	} ifsr_u;
};

struct if_interface_state {
	/*
	 * The bitmask tells which of the fields
	 * to consider:
	 * - When setting, to control which fields
	 *   are being modified;
	 * - When getting, it tells which fields are set.
	 */
	u_int8_t valid_bitmask;
#define	IF_INTERFACE_STATE_RRC_STATE_VALID		0x1
#define	IF_INTERFACE_STATE_LQM_STATE_VALID		0x2
#define	IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID	0x4

	/*
	 * Valid only for cellular interface
	 */
	u_int8_t rrc_state;
#define	IF_INTERFACE_STATE_RRC_STATE_IDLE	0x0
#define	IF_INTERFACE_STATE_RRC_STATE_CONNECTED	0x1

	/*
	 * Values normalized to the edge of the following values
	 * that are defined on <net/if.h>:
	 *  IFNET_LQM_THRESH_BAD
	 *  IFNET_LQM_THRESH_POOR
	 *  IFNET_LQM_THRESH_GOOD
	 */
	int8_t lqm_state;

	/*
	 * Indicate if the underlying link is currently
	 * available
	 */
	u_int8_t interface_availability;
#define	IF_INTERFACE_STATE_INTERFACE_AVAILABLE		0x0
#define	IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE	0x1
};

struct chain_len_stats {
	uint64_t	cls_one;
	uint64_t	cls_two;
	uint64_t	cls_three;
	uint64_t	cls_four;
	uint64_t	cls_five_or_more;
} __attribute__((__aligned__(sizeof (uint64_t))));

#endif /* PRIVATE */

#pragma pack()

/*
 * Structure defining a queue for a network interface.
 */
struct	ifqueue {
	void	*ifq_head;
	void	*ifq_tail;
	int	ifq_len;
	int	ifq_maxlen;
	int	ifq_drops;
};

#ifdef BSD_KERNEL_PRIVATE
/*
 * Internal storage of if_data. This is bound to change. Various places in the
 * stack will translate this data structure in to the externally visible
 * if_data structure above.  Note that during interface attach time, the
 * embedded if_data structure in ifnet is cleared, with the exception of
 * some non-statistics related fields.
 */
struct if_data_internal {
	/* generic interface information */
	u_char		ifi_type;	/* ethernet, tokenring, etc */
	u_char		ifi_typelen;	/* Length of frame type id */
	u_char		ifi_physical;	/* e.g., AUI, Thinnet, 10base-T, etc */
	u_char		ifi_addrlen;	/* media address length */
	u_char		ifi_hdrlen;	/* media header length */
	u_char		ifi_recvquota;	/* polling quota for receive intrs */
	u_char		ifi_xmitquota;	/* polling quota for xmit intrs */
	u_char		ifi_unused1;	/* for future use */
	u_int32_t	ifi_mtu;	/* maximum transmission unit */
	u_int32_t	ifi_metric;	/* routing metric (external only) */
	u_int32_t	ifi_baudrate;	/* linespeed */
	/* volatile statistics */
	u_int64_t	ifi_ipackets;	/* packets received on interface */
	u_int64_t	ifi_ierrors;	/* input errors on interface */
	u_int64_t	ifi_opackets;	/* packets sent on interface */
	u_int64_t	ifi_oerrors;	/* output errors on interface */
	u_int64_t	ifi_collisions;	/* collisions on csma interfaces */
	u_int64_t	ifi_ibytes;	/* total number of octets received */
	u_int64_t	ifi_obytes;	/* total number of octets sent */
	u_int64_t	ifi_imcasts;	/* packets received via multicast */
	u_int64_t	ifi_omcasts;	/* packets sent via multicast */
	u_int64_t	ifi_iqdrops;	/* dropped on input, this interface */
	u_int64_t	ifi_noproto;	/* destined for unsupported protocol */
	u_int32_t	ifi_recvtiming;	/* usec spent receiving when timing */
	u_int32_t	ifi_xmittiming;	/* usec spent xmitting when timing */
	u_int64_t	ifi_alignerrs;	/* unaligned (32-bit) input pkts */
	u_int64_t	ifi_dt_bytes;	/* Data threshold counter */
	u_int64_t	ifi_fpackets;	/* forwarded packets on interface */
	u_int64_t	ifi_fbytes;	/* forwarded bytes on interface */
	struct	timeval ifi_lastchange;	/* time of last administrative change */
	u_int32_t	ifi_hwassist;	/* HW offload capabilities */
	u_int32_t	ifi_tso_v4_mtu;	/* TCP Segment Offload IPv4 maximum segment size */
	u_int32_t	ifi_tso_v6_mtu;	/* TCP Segment Offload IPv6 maximum segment size */
};
#endif /* BSD_KERNEL_PRIVATE */

#ifdef PRIVATE
#define	if_mtu		if_data.ifi_mtu
#define	if_type		if_data.ifi_type
#define if_typelen	if_data.ifi_typelen
#define if_physical	if_data.ifi_physical
#define	if_addrlen	if_data.ifi_addrlen
#define	if_hdrlen	if_data.ifi_hdrlen
#define	if_metric	if_data.ifi_metric
#define	if_baudrate	if_data.ifi_baudrate
#define	if_hwassist	if_data.ifi_hwassist
#define	if_ipackets	if_data.ifi_ipackets
#define	if_ierrors	if_data.ifi_ierrors
#define	if_opackets	if_data.ifi_opackets
#define	if_oerrors	if_data.ifi_oerrors
#define	if_collisions	if_data.ifi_collisions
#define	if_ibytes	if_data.ifi_ibytes
#define	if_obytes	if_data.ifi_obytes
#define	if_imcasts	if_data.ifi_imcasts
#define	if_omcasts	if_data.ifi_omcasts
#define	if_iqdrops	if_data.ifi_iqdrops
#define	if_noproto	if_data.ifi_noproto
#define	if_lastchange	if_data.ifi_lastchange
#define if_recvquota	if_data.ifi_recvquota
#define	if_xmitquota	if_data.ifi_xmitquota
#endif /* PRIVATE */
#ifdef BSD_KERNEL_PRIVATE
#define	if_tso_v4_mtu	if_data.ifi_tso_v4_mtu
#define	if_tso_v6_mtu	if_data.ifi_tso_v6_mtu
#define	if_alignerrs	if_data.ifi_alignerrs
#define	if_dt_bytes	if_data.ifi_dt_bytes
#define	if_fpackets	if_data.ifi_fpackets
#define	if_fbytes	if_data.ifi_fbytes
#endif /* BSD_KERNEL_PRIVATE */

#ifdef BSD_KERNEL_PRIVATE
/*
 * Forward structure declarations for function prototypes [sic].
 */
struct proc;
struct rtentry;
struct socket;
struct ifnet_filter;
struct mbuf;
struct ifaddr;
struct tqdummy;
struct proto_hash_entry;
struct dlil_threading_info;
struct tcpstat_local;
struct udpstat_local;
#if PF
struct pfi_kif;
#endif /* PF */

/* we use TAILQs so that the order of instantiation is preserved in the list */
TAILQ_HEAD(ifnethead, ifnet);
TAILQ_HEAD(ifaddrhead, ifaddr);
LIST_HEAD(ifmultihead, ifmultiaddr);
TAILQ_HEAD(tailq_head, tqdummy);
TAILQ_HEAD(ifnet_filter_head, ifnet_filter);
TAILQ_HEAD(ddesc_head_name, dlil_demux_desc);

extern boolean_t intcoproc_unrestricted;
#endif /* BSD_KERNEL_PRIVATE */

#ifdef PRIVATE
/*
 * All of the following IF_HWASSIST_* flags are defined in kpi_interface.h as
 * IFNET_* flags. These are redefined here as constants to avoid failures to
 * build user level programs that can not include kpi_interface.h. It is
 * important to keep this in sync with the definitions in kpi_interface.h.
 * The corresponding constant for each definition is mentioned in the comment.
 *
 * Bottom 16 bits reserved for hardware checksum
 */
#define IF_HWASSIST_CSUM_IP		0x0001	/* will csum IP, IFNET_CSUM_IP */
#define IF_HWASSIST_CSUM_TCP		0x0002	/* will csum TCP, IFNET_CSUM_TCP */
#define IF_HWASSIST_CSUM_UDP		0x0004	/* will csum UDP, IFNET_CSUM_UDP */
#define IF_HWASSIST_CSUM_IP_FRAGS	0x0008	/* will csum IP fragments, IFNET_CSUM_FRAGMENT */
#define IF_HWASSIST_CSUM_FRAGMENT	0x0010	/* will do IP fragmentation, IFNET_IP_FRAGMENT */
#define IF_HWASSIST_CSUM_TCPIPV6	0x0020	/* will csum TCPv6, IFNET_CSUM_TCPIPV6 */
#define IF_HWASSIST_CSUM_UDPIPV6	0x0040	/* will csum UDPv6, IFNET_CSUM_UDP */
#define IF_HWASSIST_CSUM_FRAGMENT_IPV6	0x0080	/* will do IPv6 fragmentation, IFNET_IPV6_FRAGMENT */
#define IF_HWASSIST_CSUM_PARTIAL	0x1000	/* simple Sum16 computation, IFNET_CSUM_PARTIAL */
#define	IF_HWASSIST_CSUM_ZERO_INVERT	0x2000	/* capable of inverting csum of 0 to -0 (0xffff) */
#define IF_HWASSIST_CSUM_MASK		0xffff
#define IF_HWASSIST_CSUM_FLAGS(hwassist)	((hwassist) & IF_HWASSIST_CSUM_MASK)

/* VLAN support */
#define IF_HWASSIST_VLAN_TAGGING	0x00010000	/* supports VLAN tagging, IFNET_VLAN_TAGGING */
#define IF_HWASSIST_VLAN_MTU		0x00020000	/* supports VLAN MTU-sized packet (for software VLAN), IFNET_VLAN_MTU */

/* TCP Segment Offloading support */

#define IF_HWASSIST_TSO_V4		0x00200000	/* will do TCP Segment offload for IPv4, IFNET_TSO_IPV4 */
#define IF_HWASSIST_TSO_V6		0x00400000	/* will do TCP Segment offload for IPv6, IFNET_TSO_IPV6 */
#endif /* PRIVATE */

#ifdef PRIVATE
#define	IFXNAMSIZ	(IFNAMSIZ + 8)	/* external name (name + unit) */
#endif

#ifdef BSD_KERNEL_PRIVATE
/*
 * ifnet is private to BSD portion of kernel
 */
#include <sys/mcache.h>
#include <sys/tree.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#include <net/classq/if_classq.h>
#include <net/if_types.h>

RB_HEAD(ll_reach_tree, if_llreach);	/* define struct ll_reach_tree */


typedef errno_t (*dlil_input_func)(ifnet_t ifp, mbuf_t m_head,
    mbuf_t m_tail, const struct ifnet_stat_increment_param *s,
    boolean_t poll, struct thread *tp);
typedef errno_t (*dlil_output_func)(ifnet_t interface, mbuf_t data);

#define	if_name(ifp)	ifp->if_xname
/*
 * Structure defining a network interface.
 *
 * (Would like to call this struct ``if'', but C isn't PL/1.)
 */
struct ifnet {
	/*
	 * Lock (RW or mutex) to protect this data structure (static storage.)
	 */
	decl_lck_rw_data(, if_lock);
	void		*if_softc;	/* pointer to driver state */
	const char	*if_name;	/* name, e.g. ``en'' or ``lo'' */
	const char	*if_xname;	/* external name (name + unit) */
	struct if_description if_desc;	/* extended description */
	TAILQ_ENTRY(ifnet) if_link;	/* all struct ifnets are chained */
	TAILQ_ENTRY(ifnet) if_detaching_link; /* list of detaching ifnets */
	TAILQ_ENTRY(ifnet) if_ordered_link;	/* list of ordered ifnets */

	decl_lck_mtx_data(, if_ref_lock)
	u_int32_t	if_refflags;	/* see IFRF flags below */
	u_int32_t	if_refio;	/* number of io ops to the underlying driver */

#define	if_list		if_link
	struct ifaddrhead if_addrhead;	/* linked list of addresses per if */
#define	if_addrlist	if_addrhead
	struct ifaddr	*if_lladdr;	/* link address (first/permanent) */

	u_int32_t	if_qosmarking_mode;	/* generation to use with NECP clients */

	int		if_pcount;	/* number of promiscuous listeners */
	struct bpf_if	*if_bpf;	/* packet filter structure */
	u_short		if_index;	/* numeric abbreviation for this if  */
	short		if_unit;	/* sub-unit for lower level driver */
	short		if_timer;	/* time 'til if_watchdog called */
	short		if_flags;	/* up/down, broadcast, etc. */
	u_int32_t	if_eflags;	/* see <net/if.h> */
	u_int32_t	if_xflags;	/* see <net/if.h> */

	int		if_capabilities;	/* interface features & capabilities */
	int		if_capenable;		/* enabled features & capabilities */

	void		*if_linkmib;	/* link-type-specific MIB data */
	size_t		if_linkmiblen;	/* length of above data */

	struct if_data_internal if_data __attribute__((aligned(8)));

	ifnet_family_t		if_family;	/* value assigned by Apple */
	ifnet_subfamily_t	if_subfamily;	/* value assigned by Apple */
	uintptr_t		if_family_cookie;
	volatile dlil_input_func if_input_dlil;
	volatile dlil_output_func if_output_dlil;
	volatile ifnet_start_func if_start;
	ifnet_output_func	if_output;
	ifnet_pre_enqueue_func	if_pre_enqueue;
	ifnet_ctl_func		if_output_ctl;
	ifnet_input_poll_func	if_input_poll;
	ifnet_ctl_func		if_input_ctl;
	ifnet_ioctl_func	if_ioctl;
	ifnet_set_bpf_tap	if_set_bpf_tap;
	ifnet_detached_func	if_free;
	ifnet_demux_func	if_demux;
	ifnet_event_func	if_event;
	ifnet_framer_func	if_framer_legacy;
	ifnet_framer_extended_func if_framer;
	ifnet_add_proto_func	if_add_proto;
	ifnet_del_proto_func	if_del_proto;
	ifnet_check_multi	if_check_multi;
	struct proto_hash_entry	*if_proto_hash;
	void			*if_kpi_storage;

	u_int32_t		if_flowhash;	/* interface flow control ID */

	decl_lck_mtx_data(, if_start_lock);
	u_int32_t		if_start_flags;	/* see IFSF flags below */
	u_int32_t		if_start_req;
	u_int16_t		if_start_active; /* output is active */
	u_int16_t		if_start_delayed;
	u_int16_t		if_start_delay_qlen;
	u_int16_t		if_start_delay_idle;
	u_int64_t		if_start_delay_swin;
	u_int32_t		if_start_delay_cnt;
	u_int32_t		if_start_delay_timeout;	/* nanoseconds */
	struct timespec		if_start_cycle;	 /* restart interval */
	struct thread		*if_start_thread;

	struct ifclassq		if_snd;		/* transmit queue */
	u_int32_t		if_output_sched_model;	/* tx sched model */

	struct if_bandwidths	if_output_bw;
	struct if_bandwidths	if_input_bw;

	struct if_latencies	if_output_lt;
	struct if_latencies	if_input_lt;

	decl_lck_mtx_data(, if_flt_lock)
	u_int32_t		if_flt_busy;
	u_int32_t		if_flt_waiters;
	struct ifnet_filter_head if_flt_head;

	struct ifmultihead	if_multiaddrs;	/* multicast addresses */
	u_int32_t		if_updatemcasts; /* mcast addrs need updating */
	int			if_amcount;	/* # of all-multicast reqs */
	decl_lck_mtx_data(, if_addrconfig_lock); /* for serializing addr config */
	struct in_multi		*if_allhostsinm; /* store all-hosts inm for this ifp */

	decl_lck_mtx_data(, if_poll_lock);
	u_int16_t		if_poll_req;
	u_int16_t		if_poll_update;	/* link update */
	u_int32_t		if_poll_active;	/* polling is active */
	struct timespec		if_poll_cycle;  /* poll interval */
	struct thread		*if_poll_thread;

	struct dlil_threading_info *if_inp;

	/* allocated once along with dlil_ifnet and is never freed */
	thread_call_t		if_dt_tcall;

	struct {
		u_int32_t	length;
		union {
			u_char	buffer[8];
			u_char	*ptr;
		} u;
	} if_broadcast;
#if CONFIG_MACF_NET
	struct label		*if_label;	/* interface MAC label */
#endif

#if PF
	struct pfi_kif		*if_pf_kif;
#endif /* PF */

	decl_lck_mtx_data(, if_cached_route_lock);
	u_int32_t		if_fwd_cacheok;
	struct route		if_fwd_route;	/* cached forwarding route */
	struct route		if_src_route;	/* cached ipv4 source route */
	struct route_in6	if_src_route6;	/* cached ipv6 source route */

	decl_lck_rw_data(, if_llreach_lock);
	struct ll_reach_tree	if_ll_srcs;	/* source link-layer tree */

	void			*if_bridge;	/* bridge glue */

	u_int32_t		if_want_aggressive_drain;
	u_int32_t		if_idle_flags;	/* idle flags */
	u_int32_t		if_idle_new_flags; /* temporary idle flags */
	u_int32_t		if_idle_new_flags_mask; /* temporary mask */
	u_int32_t		if_route_refcnt; /* idle: route ref count */
	u_int32_t		if_rt_sendts;	/* last of a real time packet */

	struct if_traffic_class if_tc __attribute__((aligned(8)));
#if INET
	struct igmp_ifinfo	*if_igi;	/* for IGMPv3 */
#endif /* INET */
#if INET6
	struct mld_ifinfo	*if_mli;	/* for MLDv2 */
#endif /* INET6 */

	struct tcpstat_local	*if_tcp_stat;	/* TCP specific stats */
	struct udpstat_local	*if_udp_stat;	/* UDP specific stats */

	struct {
		int32_t		level;		/* cached logging level */
		u_int32_t	flags;		/* cached logging flags */
		int32_t		category;	/* cached category */
		int32_t		subcategory;	/* cached subcategory */
	} if_log;

	struct {
		struct ifnet	*ifp;		/* delegated ifp */
		u_int32_t	type;		/* delegated i/f type */
		u_int32_t	family;		/* delegated i/f family */
		u_int32_t	subfamily;	/* delegated i/f sub-family */
		uint32_t	expensive:1;	/* delegated i/f expensive? */
	} if_delegated;

	uuid_t			*if_agentids;	/* network agents attached to interface */
	u_int32_t		if_agentcount;

	u_int32_t		if_generation;	/* generation to use with NECP clients */
	u_int32_t		if_fg_sendts;	/* last send on a fg socket in seconds */

	u_int64_t		if_data_threshold;

	/* Total bytes in send socket buffer */
	int64_t			if_sndbyte_total __attribute__ ((aligned(8)));
	/* Total unsent bytes in send socket buffer */
	int64_t			if_sndbyte_unsent __attribute__ ((aligned(8)));
	/* count of times, when there was data to send when sleep is impending */
	uint32_t		if_unsent_data_cnt;

#if INET
	decl_lck_rw_data(, if_inetdata_lock);
	void			*if_inetdata;
#endif /* INET */
#if INET6
	decl_lck_rw_data(, if_inet6data_lock);
	void			*if_inet6data;
#endif
	decl_lck_rw_data(, if_link_status_lock);
	struct if_link_status	*if_link_status;
	struct if_interface_state	if_interface_state;
	struct if_tcp_ecn_stat *if_ipv4_stat;
	struct if_tcp_ecn_stat *if_ipv6_stat;

	struct if_lim_perf_stat if_lim_stat;
};

/* Interface event handling declarations */
extern struct eventhandler_lists_ctxt ifnet_evhdlr_ctxt;

typedef enum {
	INTF_EVENT_CODE_CREATED,
	INTF_EVENT_CODE_REMOVED,
	INTF_EVENT_CODE_STATUS_UPDATE,
	INTF_EVENT_CODE_IPADDR_ATTACHED,
	INTF_EVENT_CODE_IPADDR_DETACHED,
	INTF_EVENT_CODE_LLADDR_UPDATE,
	INTF_EVENT_CODE_MTU_CHANGED,
} intf_event_code_t;

typedef void (*ifnet_event_fn)(struct eventhandler_entry_arg, struct ifnet *, struct sockaddr *, intf_event_code_t);
EVENTHANDLER_DECLARE(ifnet_event, ifnet_event_fn);

#define	IF_TCP_STATINC(_ifp, _s) do {					\
	if ((_ifp)->if_tcp_stat != NULL)				\
		atomic_add_64(&(_ifp)->if_tcp_stat->_s, 1);		\
} while (0);

#define	IF_UDP_STATINC(_ifp, _s) do {					\
	if ((_ifp)->if_udp_stat != NULL)				\
		atomic_add_64(&(_ifp)->if_udp_stat->_s, 1);		\
} while (0);

/*
 * Valid values for if_refflags
 */
#define	IFRF_EMBRYONIC	0x1	/* ifnet is allocated; awaiting attach */
#define	IFRF_ATTACHED	0x2	/* ifnet attach is completely done */
#define	IFRF_DETACHING	0x4	/* detach has been requested */
#define	IFRF_ATTACH_MASK	\
	(IFRF_EMBRYONIC|IFRF_ATTACHED|IFRF_DETACHING)

#define	IF_FULLY_ATTACHED(_ifp)	\
	(((_ifp)->if_refflags & IFRF_ATTACH_MASK) == IFRF_ATTACHED)
/*
 * Valid values for if_start_flags
 */
#define	IFSF_FLOW_CONTROLLED	0x1	/* flow controlled */

/*
 * Structure describing a `cloning' interface.
 */
struct if_clone {
	LIST_ENTRY(if_clone) ifc_list;	/* on list of cloners */
	const char	*ifc_name;	/* name of device, e.g. `vlan' */
	size_t		ifc_namelen;	/* length of name */
	u_int32_t	ifc_minifs;	/* minimum number of interfaces */
	u_int32_t	ifc_maxunit;	/* maximum unit number */
	unsigned char	*ifc_units;	/* bitmap to handle units */
	u_int32_t	ifc_bmlen;	/* bitmap length */

	int		(*ifc_create)(struct if_clone *, u_int32_t, void *);
	int		(*ifc_destroy)(struct ifnet *);
};

#define IF_CLONE_INITIALIZER(name, create, destroy, minifs, maxunit) {	      \
	{ NULL, NULL }, name, (sizeof (name) - 1), minifs, maxunit, NULL, 0,  \
	create, destroy							      \
}

#define M_CLONE         M_IFADDR

/*
 * Macros to manipulate ifqueue.  Users of these macros are responsible
 * for serialization, by holding whatever lock is appropriate for the
 * corresponding structure that is referring the ifqueue.
 */
#define	IF_QFULL(ifq)		((ifq)->ifq_len >= (ifq)->ifq_maxlen)
#define	IF_DROP(ifq)		((ifq)->ifq_drops++)

#define	IF_ENQUEUE(ifq, m) do {						\
	(m)->m_nextpkt = NULL;						\
	if ((ifq)->ifq_tail == NULL)					\
		(ifq)->ifq_head = m;					\
	else								\
		((struct mbuf*)(ifq)->ifq_tail)->m_nextpkt = m;		\
	(ifq)->ifq_tail = m;						\
	(ifq)->ifq_len++;						\
} while (0)

#define	IF_PREPEND(ifq, m) do {						\
	(m)->m_nextpkt = (ifq)->ifq_head;				\
	if ((ifq)->ifq_tail == NULL)					\
		(ifq)->ifq_tail = (m);					\
	(ifq)->ifq_head = (m);						\
	(ifq)->ifq_len++;						\
} while (0)

#define	IF_DEQUEUE(ifq, m) do {						\
	(m) = (ifq)->ifq_head;						\
	if (m != NULL) {						\
		if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL)		\
			(ifq)->ifq_tail = NULL;				\
		(m)->m_nextpkt = NULL;					\
		(ifq)->ifq_len--;					\
	}								\
} while (0)

#define	IF_REMQUEUE(ifq, m) do {					\
	struct mbuf *_p = (ifq)->ifq_head;				\
	struct mbuf *_n = (m)->m_nextpkt;				\
	if ((m) == _p)							\
		_p = NULL;						\
	while (_p != NULL) {						\
		if (_p->m_nextpkt == (m))				\
			break;						\
		_p = _p->m_nextpkt;					\
	}								\
	VERIFY(_p != NULL || ((m) == (ifq)->ifq_head));			\
	if ((m) == (ifq)->ifq_head)					\
		(ifq)->ifq_head = _n;					\
	if ((m) == (ifq)->ifq_tail)					\
		(ifq)->ifq_tail = _p;					\
	VERIFY((ifq)->ifq_tail != NULL || (ifq)->ifq_head == NULL);	\
	VERIFY((ifq)->ifq_len != 0);					\
	--(ifq)->ifq_len;						\
	if (_p != NULL)							\
		_p->m_nextpkt = _n;					\
	(m)->m_nextpkt = NULL;						\
} while (0)

#define IF_DRAIN(ifq) do {						\
	struct mbuf *_m;						\
	for (;;) {							\
		IF_DEQUEUE(ifq, _m);					\
		if (_m == NULL)						\
			break;						\
		m_freem(_m);						\
	}								\
} while (0)

/*
 * The ifaddr structure contains information about one address
 * of an interface.  They are maintained by the different address families,
 * are allocated and attached when an address is set, and are linked
 * together so all addresses for an interface can be located.
 */
struct ifaddr {
	decl_lck_mtx_data(, ifa_lock);	/* lock for ifaddr */
	uint32_t	ifa_refcnt;	/* ref count, use IFA_{ADD,REM}REF */
	uint32_t	ifa_debug;	/* debug flags */
	struct sockaddr	*ifa_addr;	/* address of interface */
	struct sockaddr	*ifa_dstaddr;	/* other end of p-to-p link */
#define	ifa_broadaddr	ifa_dstaddr	/* broadcast address interface */
	struct sockaddr	*ifa_netmask;	/* used to determine subnet */
	struct ifnet	*ifa_ifp;	/* back-pointer to interface */
	TAILQ_ENTRY(ifaddr) ifa_link;	/* queue macro glue */
	void (*ifa_rtrequest)		/* check or clean routes (+ or -)'d */
	    (int, struct rtentry *, struct sockaddr *);
	uint32_t	ifa_flags;	/* mostly rt_flags for cloning */
	int32_t		ifa_metric;	/* cost of going out this interface */
	void (*ifa_free)(struct ifaddr *); /* callback fn for freeing */
	void (*ifa_trace)		/* callback fn for tracing refs */
	    (struct ifaddr *, int);
	void (*ifa_attached)(struct ifaddr *); /* callback fn for attaching */
	void (*ifa_detached)(struct ifaddr *); /* callback fn for detaching */
#if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
/* For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
 * are 32-bit:
 * Align to 64-bit since we cast to this to struct in6_ifaddr, which is
 * 64-bit aligned
 */
} __attribute__ ((aligned(8)));
#else
};
#endif


/*
 * Valid values for ifa_flags
 */
#define	IFA_ROUTE	RTF_UP		/* route installed (0x1) */
#define	IFA_CLONING	RTF_CLONING	/* (0x100) */

/*
 * Valid values for ifa_debug
 */
#define	IFD_ATTACHED	0x1		/* attached to list */
#define	IFD_ALLOC	0x2		/* dynamically allocated */
#define	IFD_DEBUG	0x4		/* has debugging info */
#define	IFD_LINK	0x8		/* link address */
#define	IFD_TRASHED	0x10		/* in trash list */
#define	IFD_DETACHING	0x20		/* detach is in progress */
#define	IFD_NOTREADY	0x40		/* embryonic; not yet ready */

#define	IFA_LOCK_ASSERT_HELD(_ifa)					\
	LCK_MTX_ASSERT(&(_ifa)->ifa_lock, LCK_MTX_ASSERT_OWNED)

#define	IFA_LOCK_ASSERT_NOTHELD(_ifa)					\
	LCK_MTX_ASSERT(&(_ifa)->ifa_lock, LCK_MTX_ASSERT_NOTOWNED)

#define	IFA_LOCK(_ifa)							\
	lck_mtx_lock(&(_ifa)->ifa_lock)

#define	IFA_LOCK_SPIN(_ifa)						\
	lck_mtx_lock_spin(&(_ifa)->ifa_lock)

#define	IFA_CONVERT_LOCK(_ifa) do {					\
	IFA_LOCK_ASSERT_HELD(_ifa);					\
	lck_mtx_convert_spin(&(_ifa)->ifa_lock);			\
} while (0)

#define	IFA_UNLOCK(_ifa)						\
	lck_mtx_unlock(&(_ifa)->ifa_lock)

#define	IFA_ADDREF(_ifa)						\
	ifa_addref(_ifa, 0)

#define	IFA_ADDREF_LOCKED(_ifa)						\
	ifa_addref(_ifa, 1)

#define	IFA_REMREF(_ifa) do {						\
	(void) ifa_remref(_ifa, 0);					\
} while (0)

#define	IFA_REMREF_LOCKED(_ifa)						\
	ifa_remref(_ifa, 1)

/*
 * Multicast address structure.  This is analogous to the ifaddr
 * structure except that it keeps track of multicast addresses.
 * Also, the request count here is a count of requests for this
 * address, not a count of pointers to this structure; anonymous
 * membership(s) holds one outstanding request count.
 */
struct ifmultiaddr {
	decl_lck_mtx_data(, ifma_lock);
	u_int32_t ifma_refcount;	/* reference count */
	u_int32_t ifma_anoncnt;		/* # of anonymous requests */
	u_int32_t ifma_reqcnt;		/* total requests for this address */
	u_int32_t ifma_debug;		/* see ifa_debug flags */
	u_int32_t ifma_flags;		/* see below */
	LIST_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */
	struct sockaddr *ifma_addr;	/* address this membership is for */
	struct ifmultiaddr *ifma_ll;	/* link-layer translation, if any */
	struct ifnet *ifma_ifp;		/* back-pointer to interface */
	void *ifma_protospec;		/* protocol-specific state, if any */
	void (*ifma_trace)		/* callback fn for tracing refs */
	    (struct ifmultiaddr *, int);
};

/*
 * Values for ifma_flags
 */
#define	IFMAF_ANONYMOUS		0x1	/* has anonymous request ref(s) held */

#define	IFMA_LOCK_ASSERT_HELD(_ifma)					\
	LCK_MTX_ASSERT(&(_ifma)->ifma_lock, LCK_MTX_ASSERT_OWNED)

#define	IFMA_LOCK_ASSERT_NOTHELD(_ifma)					\
	LCK_MTX_ASSERT(&(_ifma)->ifma_lock, LCK_MTX_ASSERT_NOTOWNED)

#define	IFMA_LOCK(_ifma)						\
	lck_mtx_lock(&(_ifma)->ifma_lock)

#define	IFMA_LOCK_SPIN(_ifma)						\
	lck_mtx_lock_spin(&(_ifma)->ifma_lock)

#define	IFMA_CONVERT_LOCK(_ifma) do {					\
	IFMA_LOCK_ASSERT_HELD(_ifma);					\
	lck_mtx_convert_spin(&(_ifma)->ifma_lock);			\
} while (0)

#define	IFMA_UNLOCK(_ifma)						\
	lck_mtx_unlock(&(_ifma)->ifma_lock)

#define	IFMA_ADDREF(_ifma)						\
	ifma_addref(_ifma, 0)

#define	IFMA_ADDREF_LOCKED(_ifma)					\
	ifma_addref(_ifma, 1)

#define	IFMA_REMREF(_ifma)						\
	ifma_remref(_ifma)

/*
 * Indicate whether or not the immediate interface, or the interface delegated
 * by it, is a cellular interface (IFT_CELLULAR).  Delegated interface type is
 * set/cleared along with the delegated ifp; we cache the type for performance
 * to avoid dereferencing delegated ifp each time.
 *
 * Note that this is meant to be used only for accounting and policy purposes;
 * certain places need to explicitly know the immediate interface type, and
 * this macro should not be used there.
 *
 * The test is done against IFT_CELLULAR instead of IFNET_FAMILY_CELLULAR to
 * handle certain cases where the family isn't set to the latter.
 */
#define	IFNET_IS_CELLULAR(_ifp)						\
	((_ifp)->if_type == IFT_CELLULAR ||				\
	(_ifp)->if_delegated.type == IFT_CELLULAR)

/*
 * Indicate whether or not the immediate interface, or the interface delegated
 * by it, is an ETHERNET interface.
 */
#define	IFNET_IS_ETHERNET(_ifp)						\
	((_ifp)->if_family == IFNET_FAMILY_ETHERNET ||			\
	(_ifp)->if_delegated.family == IFNET_FAMILY_ETHERNET)
/*
 * Indicate whether or not the immediate interface, or the interface delegated
 * by it, is a Wi-Fi interface (IFNET_SUBFAMILY_WIFI).  Delegated interface
 * subfamily is set/cleared along with the delegated ifp; we cache the subfamily
 * for performance to avoid dereferencing delegated ifp each time.
 *
 * Note that this is meant to be used only for accounting and policy purposes;
 * certain places need to explicitly know the immediate interface type, and
 * this macro should not be used there.
 *
 * The test is done against IFNET_SUBFAMILY_WIFI as the family may be set to
 * IFNET_FAMILY_ETHERNET (as well as type to IFT_ETHER) which is too generic.
 */
#define	IFNET_IS_WIFI(_ifp)						\
	((_ifp)->if_subfamily == IFNET_SUBFAMILY_WIFI ||		\
	(_ifp)->if_delegated.subfamily == IFNET_SUBFAMILY_WIFI)

/*
 * Indicate whether or not the immediate interface, or the interface delegated
 * by it, is a Wired interface (several families).  Delegated interface
 * family is set/cleared along with the delegated ifp; we cache the family
 * for performance to avoid dereferencing delegated ifp each time.
 *
 * Note that this is meant to be used only for accounting and policy purposes;
 * certain places need to explicitly know the immediate interface type, and
 * this macro should not be used there.
 */
#define	IFNET_IS_WIRED(_ifp)						\
	((_ifp)->if_family == IFNET_FAMILY_ETHERNET ||			\
	(_ifp)->if_delegated.family == IFNET_FAMILY_ETHERNET ||		\
	(_ifp)->if_family == IFNET_FAMILY_FIREWIRE ||			\
	(_ifp)->if_delegated.family == IFNET_FAMILY_FIREWIRE)

/*
 * Indicate whether or not the immediate WiFi interface is on an infrastructure
 * network
 */
#define	IFNET_IS_WIFI_INFRA(_ifp)				\
	((_ifp)->if_family == IFNET_FAMILY_ETHERNET &&		\
	(_ifp)->if_subfamily == IFNET_SUBFAMILY_WIFI &&		\
	!((_ifp)->if_eflags & IFEF_AWDL))

/*
 * Indicate whether or not the immediate interface, or the interface delegated
 * by it, is marked as expensive.  The delegated interface is set/cleared
 * along with the delegated ifp; we cache the flag for performance to avoid
 * dereferencing delegated ifp each time.
 *
 * Note that this is meant to be used only for policy purposes.
 */
#define	IFNET_IS_EXPENSIVE(_ifp)					\
	((_ifp)->if_eflags & IFEF_EXPENSIVE ||				\
	(_ifp)->if_delegated.expensive)

/*
 * We don't support AWDL interface delegation.
 */
#define	IFNET_IS_AWDL_RESTRICTED(_ifp)					\
	(((_ifp)->if_eflags & (IFEF_AWDL|IFEF_AWDL_RESTRICTED)) == 	\
	    (IFEF_AWDL|IFEF_AWDL_RESTRICTED))

#define	IFNET_IS_INTCOPROC(_ifp)					\
	((_ifp)->if_family == IFNET_FAMILY_ETHERNET &&			\
	 (_ifp)->if_subfamily == IFNET_SUBFAMILY_INTCOPROC)

extern struct ifnethead ifnet_head;
extern struct ifnethead ifnet_ordered_head;
extern struct ifnet **ifindex2ifnet;
extern u_int32_t if_sndq_maxlen;
extern u_int32_t if_rcvq_maxlen;
extern int if_index;
extern struct ifaddr **ifnet_addrs;
extern lck_attr_t *ifa_mtx_attr;
extern lck_grp_t *ifa_mtx_grp;
extern lck_grp_t *ifnet_lock_group;
extern lck_attr_t *ifnet_lock_attr;
extern ifnet_t lo_ifp;

extern int if_addmulti(struct ifnet *, const struct sockaddr *,
    struct ifmultiaddr **);
extern int if_addmulti_anon(struct ifnet *, const struct sockaddr *,
    struct ifmultiaddr **);
extern int if_allmulti(struct ifnet *, int);
extern int if_delmulti(struct ifnet *, const struct sockaddr *);
extern int if_delmulti_ifma(struct ifmultiaddr *);
extern int if_delmulti_anon(struct ifnet *, const struct sockaddr *);
extern void if_down(struct ifnet *);
extern int if_down_all(void);
extern void if_up(struct ifnet *);
__private_extern__ void if_updown(struct ifnet *ifp, int up);
extern int ifioctl(struct socket *, u_long, caddr_t, struct proc *);
extern int ifioctllocked(struct socket *, u_long, caddr_t, struct proc *);
extern struct ifnet *ifunit(const char *);
extern struct ifnet *ifunit_ref(const char *);
extern int ifunit_extract(const char *src, char *dst, size_t dstlen, int *unit);
extern struct ifnet *if_withname(struct sockaddr *);
extern void if_qflush(struct ifnet *, int);
extern void if_qflush_sc(struct ifnet *, mbuf_svc_class_t, u_int32_t,
    u_int32_t *, u_int32_t *, int);

extern struct if_clone *if_clone_lookup(const char *, u_int32_t *);
extern int if_clone_attach(struct if_clone *);
extern void if_clone_detach(struct if_clone *);

extern u_int32_t if_functional_type(struct ifnet *, bool);

extern errno_t if_mcasts_update(struct ifnet *);

typedef enum {
	IFNET_LCK_ASSERT_EXCLUSIVE,	/* RW: held as writer */
	IFNET_LCK_ASSERT_SHARED,	/* RW: held as reader */
	IFNET_LCK_ASSERT_OWNED,		/* RW: writer/reader, MTX: held */
	IFNET_LCK_ASSERT_NOTOWNED	/* not held */
} ifnet_lock_assert_t;

#define	IF_LLADDR(_ifp)	\
	(LLADDR(SDL(((_ifp)->if_lladdr)->ifa_addr)))

#define	IF_INDEX_IN_RANGE(_ind_) ((_ind_) > 0 && \
	(unsigned int)(_ind_) <= (unsigned int)if_index)

__private_extern__ void ifnet_lock_assert(struct ifnet *, ifnet_lock_assert_t);
__private_extern__ void ifnet_lock_shared(struct ifnet *ifp);
__private_extern__ void ifnet_lock_exclusive(struct ifnet *ifp);
__private_extern__ void ifnet_lock_done(struct ifnet *ifp);

#if INET
__private_extern__ void if_inetdata_lock_shared(struct ifnet *ifp);
__private_extern__ void if_inetdata_lock_exclusive(struct ifnet *ifp);
__private_extern__ void if_inetdata_lock_done(struct ifnet *ifp);
#endif

#if INET6
__private_extern__ void if_inet6data_lock_shared(struct ifnet *ifp);
__private_extern__ void if_inet6data_lock_exclusive(struct ifnet *ifp);
__private_extern__ void if_inet6data_lock_done(struct ifnet *ifp);
#endif

__private_extern__ void	ifnet_head_lock_shared(void);
__private_extern__ void	ifnet_head_lock_exclusive(void);
__private_extern__ void	ifnet_head_done(void);
__private_extern__ void	ifnet_head_assert_exclusive(void);

__private_extern__ errno_t ifnet_set_idle_flags_locked(ifnet_t, u_int32_t,
    u_int32_t);
__private_extern__ int ifnet_is_attached(struct ifnet *, int refio);
__private_extern__ void ifnet_incr_iorefcnt(struct ifnet *);
__private_extern__ void ifnet_decr_iorefcnt(struct ifnet *);
__private_extern__ void ifnet_set_start_cycle(struct ifnet *,
    struct timespec *);
__private_extern__ void ifnet_set_poll_cycle(struct ifnet *,
    struct timespec *);

__private_extern__ void if_attach_ifa(struct ifnet *, struct ifaddr *);
__private_extern__ void if_attach_link_ifa(struct ifnet *, struct ifaddr *);
__private_extern__ void if_detach_ifa(struct ifnet *, struct ifaddr *);
__private_extern__ void if_detach_link_ifa(struct ifnet *, struct ifaddr *);

__private_extern__ void dlil_if_lock(void);
__private_extern__ void dlil_if_unlock(void);
__private_extern__ void dlil_if_lock_assert(void);

extern struct ifaddr *ifa_ifwithaddr(const struct sockaddr *);
extern struct ifaddr *ifa_ifwithaddr_locked(const struct sockaddr *);
extern struct ifaddr *ifa_ifwithaddr_scoped(const struct sockaddr *,
    unsigned int);
extern struct ifaddr *ifa_ifwithaddr_scoped_locked(const struct sockaddr *,
    unsigned int);
extern struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *);
extern struct ifaddr *ifa_ifwithnet(const struct sockaddr *);
extern struct ifaddr *ifa_ifwithnet_scoped(const struct sockaddr *,
    unsigned int);
extern struct ifaddr *ifa_ifwithroute(int, const struct sockaddr *,
    const struct sockaddr *);
extern struct	ifaddr *ifa_ifwithroute_locked(int, const struct sockaddr *,
    const struct sockaddr *);
extern struct ifaddr *ifa_ifwithroute_scoped_locked(int,
    const struct sockaddr *, const struct sockaddr *, unsigned int);
extern struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *);
__private_extern__ struct ifaddr *ifa_ifpgetprimary(struct ifnet *, int);
extern void ifa_addref(struct ifaddr *, int);
extern struct ifaddr *ifa_remref(struct ifaddr *, int);
extern void ifa_lock_init(struct ifaddr *);
extern void ifa_lock_destroy(struct ifaddr *);
extern void ifma_addref(struct ifmultiaddr *, int);
extern void ifma_remref(struct ifmultiaddr *);

extern void ifa_init(void);

__private_extern__ struct in_ifaddr *ifa_foraddr(unsigned int);
__private_extern__ struct in_ifaddr *ifa_foraddr_scoped(unsigned int,
    unsigned int);

struct ifreq;
extern errno_t ifnet_getset_opportunistic(struct ifnet *, u_long,
    struct ifreq *, struct proc *);
extern int ifnet_get_throttle(struct ifnet *, u_int32_t *);
extern int ifnet_set_throttle(struct ifnet *, u_int32_t);
extern errno_t ifnet_getset_log(struct ifnet *, u_long,
    struct ifreq *, struct proc *);
extern int ifnet_set_log(struct ifnet *, int32_t, uint32_t, int32_t, int32_t);
extern int ifnet_get_log(struct ifnet *, int32_t *, uint32_t *, int32_t *,
    int32_t *);
extern int ifnet_notify_address(struct ifnet *, int);
extern void ifnet_notify_data_threshold(struct ifnet *);

#define IF_AFDATA_RLOCK         if_afdata_rlock
#define IF_AFDATA_RUNLOCK       if_afdata_unlock
#define IF_AFDATA_WLOCK         if_afdata_wlock
#define IF_AFDATA_WUNLOCK       if_afdata_unlock
#define IF_AFDATA_WLOCK_ASSERT  if_afdata_wlock_assert
#define IF_AFDATA_LOCK_ASSERT   if_afdata_lock_assert
#define IF_AFDATA_UNLOCK_ASSERT if_afdata_unlock_assert

static inline void
if_afdata_rlock (struct ifnet *ifp, int af)
{
	switch (af) {
#if INET
	case AF_INET:
		lck_rw_lock_shared(&ifp->if_inetdata_lock);
		break;
#endif
#if INET6
	case AF_INET6:
		lck_rw_lock_shared(&ifp->if_inet6data_lock);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

static inline void
if_afdata_runlock (struct ifnet *ifp, int af)
{
	switch (af) {
#if INET
	case AF_INET:
		lck_rw_done(&ifp->if_inetdata_lock);
		break;
#endif
#if INET6
	case AF_INET6:
		lck_rw_done(&ifp->if_inet6data_lock);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

static inline void
if_afdata_wlock (struct ifnet *ifp, int af)
{
	switch (af) {
#if INET
	case AF_INET:
		lck_rw_lock_exclusive(&ifp->if_inetdata_lock);
		break;
#endif
#if INET6
	case AF_INET6:
		lck_rw_lock_exclusive(&ifp->if_inet6data_lock);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

static inline void
if_afdata_unlock (struct ifnet *ifp, int af)
{
	switch (af) {
#if INET
	case AF_INET:
		lck_rw_done(&ifp->if_inetdata_lock);
		break;
#endif
#if INET6
	case AF_INET6:
		lck_rw_done(&ifp->if_inet6data_lock);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

static inline void
if_afdata_wlock_assert (struct ifnet *ifp, int af)
{
#if !MACH_ASSERT
#pragma unused(ifp)
#endif
	switch (af) {
#if INET
	case AF_INET:
		LCK_RW_ASSERT(&ifp->if_inetdata_lock, LCK_RW_ASSERT_EXCLUSIVE);
		break;
#endif
#if INET6
	case AF_INET6:
		LCK_RW_ASSERT(&ifp->if_inet6data_lock, LCK_RW_ASSERT_EXCLUSIVE);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

static inline void
if_afdata_unlock_assert (struct ifnet *ifp, int af)
{
#if !MACH_ASSERT
#pragma unused(ifp)
#endif
	switch (af) {
#if INET
	case AF_INET:
		LCK_RW_ASSERT(&ifp->if_inetdata_lock, LCK_RW_ASSERT_NOTHELD);
		break;
#endif
#if INET6
	case AF_INET6:
		LCK_RW_ASSERT(&ifp->if_inet6data_lock, LCK_RW_ASSERT_NOTHELD);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

static inline void
if_afdata_lock_assert (struct ifnet *ifp, int af)
{
#if !MACH_ASSERT
#pragma unused(ifp)
#endif
	switch (af) {
#if INET
	case AF_INET:
		LCK_RW_ASSERT(&ifp->if_inetdata_lock, LCK_RW_ASSERT_HELD);
		break;
#endif
#if INET6
	case AF_INET6:
		LCK_RW_ASSERT(&ifp->if_inet6data_lock, LCK_RW_ASSERT_HELD);
		break;
#endif
	default:
		VERIFY(0);
		/* NOTREACHED */
	}
	return;
}

#if INET6
struct in6_addr;
__private_extern__ struct in6_ifaddr *ifa_foraddr6(struct in6_addr *);
__private_extern__ struct in6_ifaddr *ifa_foraddr6_scoped(struct in6_addr *,
    unsigned int);
#endif /* INET6 */

__private_extern__ void if_data_internal_to_if_data(struct ifnet *ifp,
    const struct if_data_internal *if_data_int, struct if_data *if_data);
__private_extern__ void	if_data_internal_to_if_data64(struct ifnet *ifp,
    const struct if_data_internal *if_data_int, struct if_data64 *if_data64);
__private_extern__ void	if_copy_traffic_class(struct ifnet *ifp,
    struct if_traffic_class *if_tc);
__private_extern__ void	if_copy_data_extended(struct ifnet *ifp,
    struct if_data_extended *if_de);
__private_extern__ void if_copy_packet_stats(struct ifnet *ifp,
    struct if_packet_stats *if_ps);
__private_extern__ void if_copy_rxpoll_stats(struct ifnet *ifp,
    struct if_rxpoll_stats *if_rs);

__private_extern__ struct rtentry *ifnet_cached_rtlookup_inet(struct ifnet *,
    struct in_addr);
#if INET6
__private_extern__ struct rtentry *ifnet_cached_rtlookup_inet6(struct ifnet *,
    struct in6_addr *);
#endif /* INET6 */

__private_extern__ errno_t if_state_update(struct ifnet *,
    struct if_interface_state *);
__private_extern__ void if_get_state(struct ifnet *,
    struct if_interface_state *);
__private_extern__ errno_t if_probe_connectivity(struct ifnet *ifp,
    u_int32_t conn_probe);
__private_extern__ void if_lqm_update(struct ifnet *, int32_t, int);
__private_extern__ void ifnet_update_sndq(struct ifclassq *, cqev_t);
__private_extern__ void ifnet_update_rcv(struct ifnet *, cqev_t);

__private_extern__ void ifnet_flowadv(uint32_t);

__private_extern__ errno_t ifnet_set_input_bandwidths(struct ifnet *,
    struct if_bandwidths *);
__private_extern__ errno_t ifnet_set_output_bandwidths(struct ifnet *,
    struct if_bandwidths *, boolean_t);
__private_extern__ u_int64_t ifnet_output_linkrate(struct ifnet *);
__private_extern__ u_int64_t ifnet_input_linkrate(struct ifnet *);

__private_extern__ errno_t ifnet_set_input_latencies(struct ifnet *,
    struct if_latencies *);
__private_extern__ errno_t ifnet_set_output_latencies(struct ifnet *,
    struct if_latencies *, boolean_t);

__private_extern__ void ifnet_clear_netagent(uuid_t);

__private_extern__ int ifnet_set_netsignature(struct ifnet *, uint8_t,
    uint8_t, uint16_t, uint8_t *);
__private_extern__ int ifnet_get_netsignature(struct ifnet *, uint8_t,
    uint8_t *, uint16_t *, uint8_t *);

#if INET6
struct ipv6_prefix;
__private_extern__ int ifnet_set_nat64prefix(struct ifnet *,
    struct ipv6_prefix *);
__private_extern__ int ifnet_get_nat64prefix(struct ifnet *,
    struct ipv6_prefix *);
#endif

/* Required exclusive ifnet_head lock */
__private_extern__ void ifnet_remove_from_ordered_list(struct ifnet *);

__private_extern__ void ifnet_increment_generation(struct ifnet *);
__private_extern__ u_int32_t ifnet_get_generation(struct ifnet *);

/* Adding and deleting netagents will take ifnet lock */
__private_extern__ int if_add_netagent(struct ifnet *, uuid_t);
__private_extern__ int if_delete_netagent(struct ifnet *, uuid_t);

extern int if_set_qosmarking_mode(struct ifnet *, u_int32_t);
__private_extern__ uint32_t ifnet_mbuf_packetpreamblelen(struct ifnet *);
__private_extern__ void intf_event_enqueue_nwk_wq_entry(struct ifnet *ifp,
    struct sockaddr *addrp, uint32_t intf_event_code);
__private_extern__ void ifnet_update_stats_per_flow(struct ifnet_stats_per_flow *,
    struct ifnet *);
#if !CONFIG_EMBEDDED
__private_extern__ errno_t ifnet_framer_stub(struct ifnet *, struct mbuf **,
    const struct sockaddr *, const char *, const char *, u_int32_t *,
    u_int32_t *);
#endif /* !CONFIG_EMBEDDED */
__private_extern__ void ifnet_enqueue_multi_setup(struct ifnet *, uint16_t,
    uint16_t);
__private_extern__ errno_t ifnet_enqueue_mbuf(struct ifnet *, struct mbuf *,
    boolean_t, boolean_t *);
#endif /* BSD_KERNEL_PRIVATE */
#ifdef XNU_KERNEL_PRIVATE
/* for uuid.c */
__private_extern__ int uuid_get_ethernet(u_int8_t *);
#endif /* XNU_KERNEL_PRIVATE */
#endif /* !_NET_IF_VAR_H_ */