View Javadoc
1   /*
2    * Copyright 2020-2024 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.linux;
6   
7   import static oshi.software.os.linux.LinuxOperatingSystem.HAS_UDEV;
8   
9   import java.io.File;
10  import java.net.NetworkInterface;
11  import java.util.ArrayList;
12  import java.util.List;
13  import java.util.Map;
14  
15  import org.slf4j.Logger;
16  import org.slf4j.LoggerFactory;
17  
18  import com.sun.jna.platform.linux.Udev;
19  import com.sun.jna.platform.linux.Udev.UdevContext;
20  import com.sun.jna.platform.linux.Udev.UdevDevice;
21  
22  import oshi.annotation.concurrent.ThreadSafe;
23  import oshi.hardware.NetworkIF;
24  import oshi.hardware.common.AbstractNetworkIF;
25  import oshi.util.FileUtil;
26  import oshi.util.Util;
27  import oshi.util.platform.linux.SysPath;
28  
29  /**
30   * LinuxNetworks class.
31   */
32  @ThreadSafe
33  public final class LinuxNetworkIF extends AbstractNetworkIF {
34  
35      private static final Logger LOG = LoggerFactory.getLogger(LinuxNetworkIF.class);
36  
37      private int ifType;
38      private boolean connectorPresent;
39      private long bytesRecv;
40      private long bytesSent;
41      private long packetsRecv;
42      private long packetsSent;
43      private long inErrors;
44      private long outErrors;
45      private long inDrops;
46      private long collisions;
47      private long speed;
48      private long timeStamp;
49      private String ifAlias = "";
50      private IfOperStatus ifOperStatus = IfOperStatus.UNKNOWN;
51  
52      public LinuxNetworkIF(NetworkInterface netint) throws InstantiationException {
53          super(netint, queryIfModel(netint));
54          updateAttributes();
55      }
56  
57      private static String queryIfModel(NetworkInterface netint) {
58          String name = netint.getName();
59          if (!HAS_UDEV) {
60              return queryIfModelFromSysfs(name);
61          }
62          UdevContext udev = Udev.INSTANCE.udev_new();
63          if (udev != null) {
64              try {
65                  UdevDevice device = udev.deviceNewFromSyspath(SysPath.NET + name);
66                  if (device != null) {
67                      try {
68                          String devVendor = device.getPropertyValue("ID_VENDOR_FROM_DATABASE");
69                          String devModel = device.getPropertyValue("ID_MODEL_FROM_DATABASE");
70                          if (!Util.isBlank(devModel)) {
71                              if (!Util.isBlank(devVendor)) {
72                                  return devVendor + " " + devModel;
73                              }
74                              return devModel;
75                          }
76                      } finally {
77                          device.unref();
78                      }
79                  }
80              } finally {
81                  udev.unref();
82              }
83          }
84          return name;
85      }
86  
87      private static String queryIfModelFromSysfs(String name) {
88          Map<String, String> uevent = FileUtil.getKeyValueMapFromFile(SysPath.NET + name + "/uevent", "=");
89          String devVendor = uevent.get("ID_VENDOR_FROM_DATABASE");
90          String devModel = uevent.get("ID_MODEL_FROM_DATABASE");
91          if (!Util.isBlank(devModel)) {
92              if (!Util.isBlank(devVendor)) {
93                  return devVendor + " " + devModel;
94              }
95              return devModel;
96          }
97          return name;
98      }
99  
100     /**
101      * Gets network interfaces on this machine
102      *
103      * @param includeLocalInterfaces include local interfaces in the result
104      * @return A list of {@link NetworkIF} objects representing the interfaces
105      */
106     public static List<NetworkIF> getNetworks(boolean includeLocalInterfaces) {
107         List<NetworkIF> ifList = new ArrayList<>();
108         for (NetworkInterface ni : getNetworkInterfaces(includeLocalInterfaces)) {
109             try {
110                 ifList.add(new LinuxNetworkIF(ni));
111             } catch (InstantiationException e) {
112                 LOG.debug("Network Interface Instantiation failed: {}", e.getMessage());
113             }
114         }
115         return ifList;
116     }
117 
118     @Override
119     public int getIfType() {
120         return this.ifType;
121     }
122 
123     @Override
124     public boolean isConnectorPresent() {
125         return this.connectorPresent;
126     }
127 
128     @Override
129     public long getBytesRecv() {
130         return this.bytesRecv;
131     }
132 
133     @Override
134     public long getBytesSent() {
135         return this.bytesSent;
136     }
137 
138     @Override
139     public long getPacketsRecv() {
140         return this.packetsRecv;
141     }
142 
143     @Override
144     public long getPacketsSent() {
145         return this.packetsSent;
146     }
147 
148     @Override
149     public long getInErrors() {
150         return this.inErrors;
151     }
152 
153     @Override
154     public long getOutErrors() {
155         return this.outErrors;
156     }
157 
158     @Override
159     public long getInDrops() {
160         return this.inDrops;
161     }
162 
163     @Override
164     public long getCollisions() {
165         return this.collisions;
166     }
167 
168     @Override
169     public long getSpeed() {
170         return this.speed;
171     }
172 
173     @Override
174     public long getTimeStamp() {
175         return this.timeStamp;
176     }
177 
178     @Override
179     public String getIfAlias() {
180         return ifAlias;
181     }
182 
183     @Override
184     public IfOperStatus getIfOperStatus() {
185         return ifOperStatus;
186     }
187 
188     @Override
189     public boolean updateAttributes() {
190         String name = SysPath.NET + getName();
191         try {
192             File ifDir = new File(name + "/statistics");
193             if (!ifDir.isDirectory()) {
194                 return false;
195             }
196         } catch (SecurityException e) {
197             return false;
198         }
199 
200         this.timeStamp = System.currentTimeMillis();
201         this.ifType = FileUtil.getIntFromFile(name + "/type");
202         this.connectorPresent = FileUtil.getIntFromFile(name + "/carrier") > 0;
203         this.bytesSent = FileUtil.getUnsignedLongFromFile(name + "/statistics/tx_bytes");
204         this.bytesRecv = FileUtil.getUnsignedLongFromFile(name + "/statistics/rx_bytes");
205         this.packetsSent = FileUtil.getUnsignedLongFromFile(name + "/statistics/tx_packets");
206         this.packetsRecv = FileUtil.getUnsignedLongFromFile(name + "/statistics/rx_packets");
207         this.outErrors = FileUtil.getUnsignedLongFromFile(name + "/statistics/tx_errors");
208         this.inErrors = FileUtil.getUnsignedLongFromFile(name + "/statistics/rx_errors");
209         this.collisions = FileUtil.getUnsignedLongFromFile(name + "/statistics/collisions");
210         this.inDrops = FileUtil.getUnsignedLongFromFile(name + "/statistics/rx_dropped");
211         long speedMbps = FileUtil.getUnsignedLongFromFile(name + "/speed");
212         // speed may be -1 from file.
213         this.speed = speedMbps < 0 ? 0 : speedMbps * 1000000L;
214         this.ifAlias = FileUtil.getStringFromFile(name + "/ifalias");
215         this.ifOperStatus = parseIfOperStatus(FileUtil.getStringFromFile(name + "/operstate"));
216 
217         return true;
218     }
219 
220     private static IfOperStatus parseIfOperStatus(String operState) {
221         switch (operState) {
222         case "up":
223             return IfOperStatus.UP;
224         case "down":
225             return IfOperStatus.DOWN;
226         case "testing":
227             return IfOperStatus.TESTING;
228         case "dormant":
229             return IfOperStatus.DORMANT;
230         case "notpresent":
231             return IfOperStatus.NOT_PRESENT;
232         case "lowerlayerdown":
233             return IfOperStatus.LOWER_LAYER_DOWN;
234         case "unknown":
235         default:
236             return IfOperStatus.UNKNOWN;
237         }
238     }
239 }