patchpanel: track interface index in ShillClient::Device

This patch is the first step in a more consistent strategy for creating
and cleaning any state associated with interface indexes.

This patch centralizes the interface name -> interface index map into
the System class and updateds ShillClient to pass the interface index of
into ShillClient::Device structs.

A follow-up patch will pass the interface index down to the various
subprocesses like ndproxy and multicast_forwader.

/var/log/net.log example:

INFO patchpaneld[1942]: INFO patchpaneld: [shill_client.cc(211)] Default
  physical device changed from {ifname: eth0, ifindex: 2, type: Ethernet,
  service: /service/2} to {ifname: rmnet_data0, ifindex: 4, type:
  Cellular, service: /service/5}

BUG=b:225282717
TEST=FEATURES=test emerge-$BOARD patchpanel

Change-Id: I5322a24225baabe961f5c57e45a965c6ba9f0728
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3534488
Reviewed-by: Taoyu Li <taoyl@chromium.org>
Commit-Queue: Hugo Benichi <hugobenichi@google.com>
Tested-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/system.h b/patchpanel/system.h
index a517f7c..0fe7cdc 100644
--- a/patchpanel/system.h
+++ b/patchpanel/system.h
@@ -10,6 +10,7 @@
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
+#include <map>
 #include <string>
 
 namespace patchpanel {
@@ -19,9 +20,10 @@
 // it's 32 bits on 32-bit platform and 64 bits on 64-bit one.
 using ioctl_req_t = unsigned long;  // NOLINT(runtime/int)
 
-// Stateless class used for holding all utility functions with side
-// effects on the environment. Facilitates mocking these functions in unit
-// tests.
+// Class used for:
+//  - holding all utility functions with side effects on the environment.
+//  - wrapping commonly used system calls.
+// This class facilitates mocking these functions in unit tests.
 class System {
  public:
   // Enum used for restricting the possible paths that SysNetSet can write to.
@@ -62,9 +64,23 @@
 
   virtual pid_t WaitPid(pid_t pid, int* wstatus, int options = 0);
 
+  // Return the interface name of the network interface with index |ifindex|, or
+  // empty string if it fails.
+  virtual std::string IfIndextoname(int ifindex);
+  // Return the index of the interface with name |ifname|, or 0 if it fails.
+  virtual uint32_t IfNametoindex(const std::string& ifname);
+
   static bool Write(const std::string& path, const std::string& content);
 
  private:
+  // A map used for remembering the interface index of an interface. This
+  // information is necessary when cleaning up the state of various subsystems
+  // in patchpanel that directly references the interface index. However after
+  // receiving the interface removal event (RTM_DELLINK event or shill DBus
+  // event), the interface index cannot be retrieved anymore. A new entry is
+  // only added when a new upstream network interface appears, and entries are
+  // not removed.
+  std::map<std::string, int> if_nametoindex_;
 };
 
 }  // namespace patchpanel