-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsdn_cmd.cpp
executable file
·249 lines (207 loc) · 6.56 KB
/
sdn_cmd.cpp
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
#include "sdn_cmd.h"
SdnReporter::SdnReporter()
{
runCount = 0;
reportInterval = DEFAULT_TOPO_REPORT_SEC;
nodeList.clear();
mat.clear();
posList.clear();
}
SdnReporter::~SdnReporter()
{
}
void SdnReporter::setPosListFromTopo()
{
TopoGraph& topo = TopoGraph::getInstance();
for (auto it = nodeList.begin(); it != nodeList.end(); it++) {
posList[*it] = topo.getNodePos(*it);
}
}
size_t SdnReporter::serializeTopo(char* buf)
{
char* p = buf;
size_t nodeCount = nodeList.size();
if (nodeCount == 0) {
cerr << "No topo information!\n";
return 0;
}
*p = (char) nodeCount;
p++;
// 在线节点列表
for (size_t i = 0; i < nodeCount; i++) {
*p = (char) ((nodeList[i] & 0xFF000000) >> 24);
p++;
}
// 邻接矩阵
for (size_t i = 0; i < nodeCount; i++) {
for (size_t j = 0; j < nodeCount; j++) {
*p = mat[i][j];
p++;
}
}
// 除汇聚节点外,其他节点与汇聚节点的距离
size_t len = 16 * (nodeCount - 1);
NodeConfig& config = NodeConfig::getInstance();
in_addr_t sinkIP = config.getSinkNodeIP();
Position sinkPos(config.getPositionX(), config.getPositionY());
for (size_t i = 0; i < nodeCount; i++) {
if (nodeList[i] == sinkIP)
continue;
Position pos = posList[nodeList[i]];
std::string posX_s = std::to_string(pos.x - sinkPos.x);
std::string posY_s = std::to_string(pos.y - sinkPos.y);
memset(p, 0, 32);
memcpy(p, posX_s.c_str(), posX_s.size());
memcpy(p + 16, posY_s.c_str(), posY_s.size());
p += 32;
}
return 1 + nodeCount + nodeCount * nodeCount + 32 * (nodeCount - 1);
}
void SdnReporter::run()
{
int send_sock;
int sendLen;
struct sockaddr_in send_addr;
char sendBuf[TOPO_PKT_MAX_LEN];
SdnReporter& reporter = SdnReporter::getInstance();
NodeConfig& config = NodeConfig::getInstance();
TopoGraph& topo = TopoGraph::getInstance();
if (config.getNodeType() != NodeType::sink) {
cout << "SdnReporter thread exited: This node is not a sink node.\n";
return;
}
if (runCount == 0) {
runCount++;
} else {
cout << "SdnReporter thread exited: a thread is already running.\n";
return;
}
memset(sendBuf, 0, TOPO_PKT_MAX_LEN);
// UDP发送套接字基本设置
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
memset(&send_addr, 0, sizeof(send_addr));
send_addr.sin_family = AF_INET;
send_addr.sin_addr.s_addr = config.getControllerIP();
send_addr.sin_port = hton16(PORT_SDN);
// 循环定期发送拓扑信息给控制器
while (stopRequested() == false) {
sleep_for(seconds(reporter.getReportInterval()));
topo.toMatrix(reporter.nodeList, reporter.mat);
reporter.setPosListFromTopo();
sendLen = reporter.serializeTopo(sendBuf);
sendto(send_sock, sendBuf, sendLen, 0, (struct sockaddr*)&send_addr, sizeof(send_addr));
cout << "Topo uploaded!\n";
}
runCount--;
cout << "SdnReporter::run() exit!\n";
}
SdnListener::SdnListener()
{
runCount = 0;
in_addr tmp;
char networkIP_s[INET_ADDRSTRLEN] = "192.168.2.0";
inet_pton(AF_INET, networkIP_s, &tmp);
networkIP = tmp.s_addr;
}
SdnListener::~SdnListener()
{
}
SdnCmdType SdnListener::checkCmdType(char* buf)
{
if (strstr(buf, "node") == 0) {
return SdnCmdType::startVideo;
} else if (strstr(buf, "End") == 0) {
return SdnCmdType::endVideo;
} else {
return SdnCmdType::unknown;
}
}
in_addr_t SdnListener::numstr2IP(char* buf)
{
in_addr_t res = networkIP;
while (1) {
size_t tail = strlen(buf) - 1;
if (buf[tail] == '\n') {
buf[tail] = 0;
} else {
break;
}
}
std::string str(buf);
uint32_t ip = std::stoi(str) + 99;
res = res & (ip << 24);
return res;
}
void SdnListener::run()
{
int recv_sock;
int recvLen;
socklen_t recv_sock_len;
in_addr_t targetNodeIP;
struct sockaddr_in recv_addr;
SdnCmdType cmdType;
char recvBuf[SDN_CMD_MAX_LEN];
NodeConfig& config = NodeConfig::getInstance();
if (config.getNodeType() != NodeType::sink) {
cout << "SdnListener thread exited: This node is not a sink node.\n";
return;
}
if (runCount == 0) {
runCount++;
} else {
cout << "SdnListener thread exited: a thread is already running.\n";
return;
}
memset(recvBuf, 0, SDN_CMD_MAX_LEN);
// UDP接收套接字基本设置
recv_sock = socket(PF_INET, SOCK_DGRAM, 0);
struct timeval recvTimeout; // recvfrom()的超时时间
recvTimeout.tv_sec = 3;
recvTimeout.tv_usec = 0;
if (setsockopt(recv_sock, SOL_SOCKET, SO_RCVTIMEO, &recvTimeout, sizeof(recvTimeout)) == -1) {
cerr << __func__ << "setsockopt() failed!\n";
}
memset(&recv_addr, 0, sizeof(recv_addr));
recv_addr.sin_family = AF_INET;
recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
recv_addr.sin_port = htons(PORT_SDN);
if (bind(recv_sock, (struct sockaddr*)&recv_addr, sizeof(recv_addr)) == -1) {
cerr << __func__ << " : bind() error\n";
return;
}
// 监听并处理 SDN 命令
char ipAddr_s[INET_ADDRSTRLEN];
while (stopRequested() == false) {
memset(recvBuf, 0, SDN_CMD_MAX_LEN);
memset(ipAddr_s, 0, INET_ADDRSTRLEN);
recv_sock_len = sizeof(recv_addr);
recvLen = recvfrom(recv_sock, recvBuf, SDN_CMD_MAX_LEN, 0, (struct sockaddr*)&recv_addr, &recv_sock_len);
if (recvLen <= 0) {
if (errno == EAGAIN) {
// cout << "No SDN packet recved.\n";
} else {
cerr << "Error accured when recving SDN packets!\n";
}
continue;
}
recvBuf[recvLen] = 0;
cmdType = checkCmdType(recvBuf);
switch (cmdType) {
case SdnCmdType::startVideo :
targetNodeIP = numstr2IP(recvBuf);
inet_ntop(AF_INET, &targetNodeIP, ipAddr_s, INET_ADDRSTRLEN);
cout << "SDN commmand: start video at " << ipAddr_s << endl;
break;
case SdnCmdType::endVideo :
targetNodeIP = numstr2IP(recvBuf);
inet_ntop(AF_INET, &targetNodeIP, ipAddr_s, INET_ADDRSTRLEN);
cout << "SDN commmand: end video at " << ipAddr_s << endl;
break;
default:
cout << "Unknown SDN command type!\n";
break;
}
}
runCount--;
cout << "SdnListener::run() exit!\n";
}