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
|
#include "config.h"
#include "dns_updater.hpp"
#include "network_manager.hpp"
#include "rtnetlink_server.hpp"
#include "types.hpp"
#include "watch.hpp"
#include <linux/netlink.h>
#include <functional>
#include <memory>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/manager.hpp>
#include <sdeventplus/event.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
using phosphor::logging::elog;
using phosphor::logging::entry;
using phosphor::logging::level;
using phosphor::logging::log;
using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
constexpr char NETWORK_STATE_FILE[] = "/run/systemd/netif/state";
constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
namespace phosphor
{
namespace network
{
std::unique_ptr<phosphor::network::Manager> manager = nullptr;
std::unique_ptr<Timer> refreshObjectTimer = nullptr;
std::unique_ptr<Timer> restartTimer = nullptr;
/** @brief refresh the network objects. */
void refreshObjects()
{
if (manager)
{
log<level::INFO>("Refreshing the objects.");
manager->createChildObjects();
log<level::INFO>("Refreshing complete.");
}
}
/** @brief restart the systemd networkd. */
void restartNetwork()
{
if (manager)
{
manager->restartSystemdUnit("systemd-networkd.service");
}
}
void initializeTimers()
{
auto event = sdeventplus::Event::get_default();
refreshObjectTimer =
std::make_unique<Timer>(event, std::bind(refreshObjects));
restartTimer = std::make_unique<Timer>(event, std::bind(restartNetwork));
}
} // namespace network
} // namespace phosphor
void createNetLinkSocket(phosphor::Descriptor& smartSock)
{
// RtnetLink socket
auto fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
if (fd < 0)
{
log<level::ERR>("Unable to create the net link socket",
entry("ERRNO=%d", errno));
elog<InternalFailure>();
}
smartSock.set(fd);
}
int main(int argc, char* argv[])
{
phosphor::network::initializeTimers();
auto bus = sdbusplus::bus::new_default();
// Need sd_event to watch for OCC device errors
sd_event* event = nullptr;
auto r = sd_event_default(&event);
if (r < 0)
{
log<level::ERR>("Error creating a default sd_event handler");
return r;
}
phosphor::network::EventPtr eventPtr{event};
event = nullptr;
// Attach the bus to sd_event to service user requests
bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
// Add sdbusplus Object Manager for the 'root' path of the network manager.
sdbusplus::server::manager::manager objManager(bus, DEFAULT_OBJPATH);
bus.request_name(DEFAULT_BUSNAME);
phosphor::network::manager = std::make_unique<phosphor::network::Manager>(
bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
// create the default network files if the network file
// is not there for any interface.
// Parameter false means don't create the network
// files forcefully.
if (phosphor::network::manager->createDefaultNetworkFiles(false))
{
// if files created restart the network.
// don't need to call the create child objects as eventhandler
// will create it.
phosphor::network::restartNetwork();
}
else
{
// this will add the additional fixes which is needed
// in the existing network file.
phosphor::network::manager->writeToConfigurationFile();
// whenever the configuration file gets written it restart
// the network which creates the network objects
}
// RtnetLink socket
phosphor::Descriptor smartSock;
createNetLinkSocket(smartSock);
// RTNETLINK event handler
phosphor::network::rtnetlink::Server svr(eventPtr, smartSock);
// DNS entry handler
phosphor::network::inotify::Watch watch(
eventPtr, NETWORK_STATE_FILE,
std::bind(&phosphor::network::dns::updater::processDNSEntries,
std::placeholders::_1));
// At this point, we have registered for the notifications for future
// events. However, if the file is already populated before this, then
// they won't ever get notified and thus we need to read once before
// waiting on change events
phosphor::network::dns::updater::processDNSEntries(NETWORK_STATE_FILE);
sd_event_loop(eventPtr.get());
}
|