blob: c5cff87182f8fed5fe65f920f3915951956608fe [file] [log] [blame]
Nan Zhou14fe6692021-06-08 16:35:44 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "nemora.hpp"
16
17#include "default_addresses.h"
18
19#include <netinet/in.h>
20#include <time.h>
21#include <unistd.h>
22
23#include <phosphor-logging/log.hpp>
24#include <sdbusplus/bus.hpp>
25#include <sdbusplus/exception.hpp>
26
27#include <cstdint>
28#include <cstring>
29#include <functional>
30#include <iostream>
31#include <variant>
32
33using phosphor::logging::level;
34using phosphor::logging::log;
35using sdbusplus::exception::SdBusError;
36
37constexpr auto MAC_FORMAT = "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx";
38constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
39constexpr auto NETWORK_INTERFACE = "xyz.openbmc_project.Network";
40constexpr auto PROP_INTERFACE = "org.freedesktop.DBus.Properties";
41constexpr auto IFACE_ROOT = "/xyz/openbmc_project/network/";
42
43bool Nemora::ParseMac(const std::string& mac_addr, MacAddr* mac)
44{
45 int ret =
46 sscanf(mac_addr.c_str(), MAC_FORMAT, mac->octet, mac->octet + 1,
47 mac->octet + 2, mac->octet + 3, mac->octet + 4, mac->octet + 5);
48 return (ret == MAC_ADDR_SIZE);
49}
50
51bool Nemora::GetMacAddr(MacAddr* mac, const std::string& iface_path)
52{
53 if (mac == nullptr)
54 {
55 log<level::ERR>("Nemora::GetMacAddr MAC Address is nullptr");
56 return false;
57 }
58 auto dbus = sdbusplus::bus::new_default();
59 sdbusplus::message::message reply;
60
61 try
62 {
63 auto networkd_call = dbus.new_method_call(
64 NETWORK_INTERFACE, iface_path.c_str(), PROP_INTERFACE, "Get");
65 networkd_call.append(MAC_INTERFACE, "MACAddress");
66
67 reply = dbus.call(networkd_call);
68 }
69 catch (const SdBusError& e)
70 {
71 log<level::ERR>(
72 "Nemora::GetMacAddr failed to call Network D-Bus interface");
73 return false;
74 }
75
76 std::variant<std::string> result;
77 reply.read(result);
78 auto mac_addr = std::get<std::string>(result);
79 if (!ParseMac(mac_addr, mac))
80 {
81 log<level::ERR>("Nemora::GetMacAddr Failed to parse MAC Address");
82 return false;
83 }
84 return true;
85}
86
87void Nemora::InitEventData()
88{
89 event_data_.type = NemoraDatagramType::NemoraEvent;
90
91 // UDP IPv4 addr for POST
92 event_data_.destination.sin_family = AF_INET;
93 event_data_.destination.sin_port = htons(DEFAULT_ADDRESSES_TARGET_PORT);
94
95 // UDP IPv6 addr for POST
96 event_data_.destination6.sin6_family = AF_INET6;
97 event_data_.destination6.sin6_port = htons(DEFAULT_ADDRESSES_TARGET_PORT);
98}
99
100Nemora::Nemora()
101{
102 InitEventData();
103}
104
105Nemora::Nemora(const std::string& iface_name, const in_addr ipv4,
106 const in6_addr ipv6) :
107 socketManager_(),
108 hostManager_(), iface_path_{std::string(IFACE_ROOT) + iface_name}
109{
110 InitEventData();
111 event_data_.destination.sin_addr = ipv4;
112 event_data_.destination6.sin6_addr = ipv6;
113}
114
115void Nemora::UdpPoll()
116{
117 auto postcodes = hostManager_.DrainPostcodes();
118
119 // Don't bother updating if there is no POST code
120 // EC supports a flag EC_NEMORA_UDP_CONFIG_MASK_PERIODIC to send
121 // periodic updates, which is non-POR for gBMC for now.
122 bool shouldBroadcast = !postcodes.empty();
123
124 UpdateEventData(std::move(postcodes));
125
126 log<level::INFO>("UpdateEventData gets called.");
127
128 if (shouldBroadcast)
129 {
130 log<level::INFO>("Should broadcast");
131 std::lock_guard<std::mutex> lock(event_data_mutex_);
132 socketManager_.SendDatagram(static_cast<NemoraDatagram*>(&event_data_));
133 }
134
135 sleep(20);
136}
137
138void Nemora::UpdateEventData(std::vector<uint64_t>&& postcodes)
139{
140 MacAddr mac;
141 GetMacAddr(&mac, iface_path_);
142
143 std::lock_guard<std::mutex> lock(event_data_mutex_);
144
145 memcpy(event_data_.mac, mac.octet, sizeof(MacAddr));
146
147 event_data_.postcodes = std::move(postcodes);
148 event_data_.sent_time_s = time(0);
149}