Skip to content

Commit 0a9a6a9

Browse files
committed
test lacp
1 parent e86737a commit 0a9a6a9

File tree

7 files changed

+494
-4
lines changed

7 files changed

+494
-4
lines changed

lib/lacp.c

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ static bool member_may_enable__(struct member *) OVS_REQUIRES(mutex);
168168

169169
static unixctl_cb_func lacp_unixctl_show;
170170
static unixctl_cb_func lacp_unixctl_show_stats;
171+
static unixctl_cb_func lacp_unixctl_set;
171172

172173
/* Populates 'pdu' with a LACP PDU comprised of 'actor' and 'partner'. */
173174
static void
@@ -229,6 +230,8 @@ lacp_init(void)
229230
lacp_unixctl_show, NULL);
230231
unixctl_command_register("lacp/show-stats", "[port]", 0, 1,
231232
lacp_unixctl_show_stats, NULL);
233+
unixctl_command_register("lacp/set", "[port]", 3, INT_MAX,
234+
lacp_unixctl_set, NULL);
232235
}
233236

234237
static void
@@ -940,6 +943,34 @@ lacp_find(const char *name) OVS_REQUIRES(mutex)
940943
return NULL;
941944
}
942945

946+
static struct member *
947+
lacp_member_find(struct lacp *lacp, const char *name) OVS_REQUIRES(mutex)
948+
{
949+
struct member *member;
950+
951+
HMAP_FOR_EACH_SAFE (member, node, &lacp->members) {
952+
if (!strcmp(member->name, name)) {
953+
return member;
954+
}
955+
}
956+
957+
return NULL;
958+
}
959+
960+
static struct member *
961+
lacp_member_find_by_key(struct lacp *lacp, uint16_t key) OVS_REQUIRES(mutex)
962+
{
963+
struct member *member;
964+
965+
HMAP_FOR_EACH_SAFE (member, node, &lacp->members) {
966+
if (member->port_id == key) {
967+
return member;
968+
}
969+
}
970+
971+
return NULL;
972+
}
973+
943974
static void
944975
ds_put_lacp_state(struct ds *ds, uint8_t state)
945976
{
@@ -1219,5 +1250,241 @@ lacp_get_member_stats(const struct lacp *lacp, const void *member_,
12191250
}
12201251
ovs_mutex_unlock(&mutex);
12211252
return ret;
1253+
}
1254+
1255+
void
1256+
lacp_port_set(struct unixctl_conn *conn, struct lacp *lacp, const char *parms)
1257+
{
1258+
char *value;
1259+
char *key;
1260+
1261+
while (ofputil_parse_key_value(&parms, &key, &value)) {
1262+
lacp->update = false;
1263+
uint32_t tmp;
1264+
if (nullable_string_is_equal(key, "status")) {
1265+
if (strstr(value, "active")) {
1266+
lacp->active = true;
1267+
}
1268+
if (strstr(value, "negotiated")) {
1269+
lacp->negotiated = true;
1270+
}
12221271

1272+
} else if (nullable_string_is_equal(key, "sys_id")) {
1273+
if (!eth_addr_from_string(value, &lacp->sys_id)) {
1274+
unixctl_command_reply_error(conn, "invalid port sys_id");
1275+
return;
1276+
}
1277+
} else if (nullable_string_is_equal(key, "sys_priority")) {
1278+
if (!str_to_uint(value, 10, &tmp)) {
1279+
unixctl_command_reply_error(conn, "invalid port sys_prority");
1280+
return;
1281+
}
1282+
lacp->sys_priority = htons(tmp);
1283+
} else if (nullable_string_is_equal(key, "key")) {
1284+
if (!str_to_uint(value, 10, &tmp)) {
1285+
unixctl_command_reply_error(conn, "invalid port key");
1286+
return;
1287+
}
1288+
key = htons(tmp);
1289+
lacp->key_member = lacp_member_find_by_key(lacp, key);
1290+
}
1291+
}
1292+
}
1293+
1294+
uint8_t
1295+
lacp_state_from_str(const char *s)
1296+
{
1297+
uint8_t state = 0;
1298+
if (strstr(s, "activity")) {
1299+
state |= LACP_STATE_ACT;
1300+
}
1301+
if (strstr(s, "timeout")) {
1302+
state |= LACP_STATE_TIME;
1303+
}
1304+
if (strstr(s, "aggregation")) {
1305+
state |= LACP_STATE_AGG;
1306+
}
1307+
if (strstr(s, "synchronized")) {
1308+
state |= LACP_STATE_SYNC;
1309+
}
1310+
if (strstr(s, "collecting")) {
1311+
state |= LACP_STATE_COL;
1312+
}
1313+
if (strstr(s, "distributing")) {
1314+
state |= LACP_STATE_DIST;
1315+
}
1316+
if (strstr(s, "defaulted")) {
1317+
state |= LACP_STATE_DEF;
1318+
}
1319+
if (strstr(s, "expired")) {
1320+
state |= LACP_STATE_EXP;
1321+
}
1322+
return state;
1323+
}
1324+
1325+
void
1326+
lacp_member_set(struct unixctl_conn *conn, struct member *member,
1327+
const char *op, const char *parms)
1328+
{
1329+
char *value;
1330+
char *key;
1331+
// status=+current+attached,port_id=1,port_priority=65535,may_enable=true
1332+
if (nullable_string_is_equal(op, "member")) {
1333+
while (ofputil_parse_key_value(&parms, &key, &value)) {
1334+
uint32_t tmp;
1335+
if (nullable_string_is_equal(key, "port_id")) {
1336+
if (!str_to_uint(value, 10, &tmp)) {
1337+
unixctl_command_reply_error(conn, "invalid member "
1338+
"port_id");
1339+
return;
1340+
}
1341+
member->port_id = htons(tmp);
1342+
} else if (nullable_string_is_equal(key, "port_priority")) {
1343+
if (!str_to_uint(value, 10, &tmp)) {
1344+
unixctl_command_reply_error(conn, "invalid member "
1345+
"port_priority");
1346+
return;
1347+
}
1348+
member->port_priority = htons(tmp);
1349+
} else if (nullable_string_is_equal(key, "status")) {
1350+
if (strstr(value, "current")) {
1351+
member->status = LACP_CURRENT;
1352+
member->carrier_up = true;
1353+
} else if (strstr(value, "expired")) {
1354+
member->status = LACP_EXPIRED;
1355+
} else if (strstr(value, "defaulted")) {
1356+
member->status = LACP_DEFAULTED;
1357+
}
1358+
1359+
if (strstr(value, "attached")) {
1360+
member->attached = true;
1361+
}
1362+
}
1363+
}
1364+
} else if (nullable_string_is_equal(op, "actor")) {
1365+
while (ofputil_parse_key_value(&parms, &key, &value)) {
1366+
uint32_t tmp;
1367+
if (nullable_string_is_equal(key, "sys_id")) {
1368+
if (!eth_addr_from_string(value, &member->ntt_actor.sys_id)) {
1369+
unixctl_command_reply_error(conn, "invalid member "
1370+
"actor sys_id");
1371+
return;
1372+
}
1373+
} else if (nullable_string_is_equal(key, "sys_priority")) {
1374+
if (!str_to_uint(value, 10, &tmp)) {
1375+
unixctl_command_reply_error(conn, "invalid member "
1376+
"actor sys_priority");
1377+
return;
1378+
}
1379+
member->ntt_actor.sys_priority = htons(tmp);
1380+
} else if (nullable_string_is_equal(key, "port_id")) {
1381+
if (!str_to_uint(value, 10, &tmp)) {
1382+
unixctl_command_reply_error(conn, "invalid member "
1383+
"actor port_id");
1384+
return;
1385+
}
1386+
member->ntt_actor.port_id = htons(tmp);
1387+
} else if (nullable_string_is_equal(key, "port_priority")) {
1388+
if (!str_to_uint(value, 10, &tmp)) {
1389+
unixctl_command_reply_error(conn, "invalid member "
1390+
"actor port_priority");
1391+
return;
1392+
}
1393+
member->ntt_actor.port_priority = htons(tmp);
1394+
} else if (nullable_string_is_equal(key, "key")) {
1395+
if (!str_to_uint(value, 10, &tmp)) {
1396+
unixctl_command_reply_error(conn, "invalid member "
1397+
"actor key");
1398+
return;
1399+
}
1400+
member->ntt_actor.key = htons(tmp);
1401+
} else if (nullable_string_is_equal(key, "state")) {
1402+
member->ntt_actor.state = lacp_state_from_str(value);
1403+
VLOG_INFO("member->ntt_actor.state (%p) (%d)",
1404+
&(member->ntt_actor.state), member->ntt_actor.state);
1405+
}
1406+
}
1407+
} else if (nullable_string_is_equal(op, "partner")) {
1408+
while (ofputil_parse_key_value(&parms, &key, &value)) {
1409+
uint32_t tmp;
1410+
if (nullable_string_is_equal(key, "sys_id")) {
1411+
if (!eth_addr_from_string(value, &member->partner.sys_id)) {
1412+
unixctl_command_reply_error(conn, "invalid member "
1413+
"partner sys_id");
1414+
return;
1415+
}
1416+
} else if (nullable_string_is_equal(key, "sys_priority")) {
1417+
if (!str_to_uint(value, 10, &tmp)) {
1418+
unixctl_command_reply_error(conn, "invalid member "
1419+
"partner sys_priority");
1420+
return;
1421+
}
1422+
member->partner.sys_priority = htons(tmp);
1423+
} else if (nullable_string_is_equal(key, "port_id")) {
1424+
if (!str_to_uint(value, 10, &tmp)) {
1425+
unixctl_command_reply_error(conn, "invalid member "
1426+
"partner port_id");
1427+
return;
1428+
}
1429+
member->partner.port_id = htons(tmp);
1430+
} else if (nullable_string_is_equal(key, "port_priority")) {
1431+
if (!str_to_uint(value, 10, &tmp)) {
1432+
unixctl_command_reply_error(conn, "invalid member "
1433+
"partner port_priority");
1434+
return;
1435+
}
1436+
member->partner.port_priority = htons(tmp);
1437+
} else if (nullable_string_is_equal(key, "key")) {
1438+
if (!str_to_uint(value, 10, &tmp)) {
1439+
unixctl_command_reply_error(conn, "invalid member "
1440+
"partner key");
1441+
return;
1442+
}
1443+
member->partner.key = htons(tmp);
1444+
} else if (nullable_string_is_equal(key, "state")) {
1445+
member->partner.state = lacp_state_from_str(value);
1446+
}
1447+
}
1448+
} else {
1449+
unixctl_command_reply_error(conn, "invalid member op");
1450+
}
1451+
timer_set_duration(&member->tx, LACP_FAST_TIME_TX);
1452+
timer_set_duration(&member->rx, LACP_FAST_TIME_TX);
1453+
}
1454+
1455+
static void
1456+
lacp_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
1457+
void *aux OVS_UNUSED) OVS_EXCLUDED(mutex)
1458+
{
1459+
struct member *member;
1460+
struct lacp *lacp;
1461+
1462+
lacp_lock();
1463+
lacp = lacp_find(argv[1]);
1464+
if (!lacp) {
1465+
unixctl_command_reply_error(conn, "lacp port not found");
1466+
goto out;
1467+
}
1468+
1469+
if (nullable_string_is_equal(argv[2], "port")) {
1470+
lacp_port_set(conn, lacp, argv[3]);
1471+
} else if (nullable_string_is_equal(argv[2], "member")) {
1472+
member = lacp_member_find(lacp, argv[3]);
1473+
if (!member) {
1474+
unixctl_command_reply_error(conn, "lacp member not found");
1475+
goto out;
1476+
}
1477+
if (argc < 5) {
1478+
unixctl_command_reply_error(conn, "invalid member parms");
1479+
goto out;
1480+
}
1481+
lacp_member_set(conn, member, argv[4], argv[5]);
1482+
} else {
1483+
unixctl_command_reply_error(conn, "invalid op type");
1484+
goto out;
1485+
}
1486+
1487+
out:
1488+
unixctl_command_reply(conn, NULL);
1489+
lacp_unlock();
12231490
}

ofproto/ofproto-dpif.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "nx-match.h"
4141
#include "odp-util.h"
4242
#include "odp-execute.h"
43+
#include "ofproto/ofproto.h"
4344
#include "ofproto/ofproto-dpif.h"
4445
#include "ofproto/ofproto-provider.h"
4546
#include "ofproto-dpif-ipfix.h"
@@ -3528,7 +3529,6 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size)
35283529
struct ofport_dpif *port = port_;
35293530
struct eth_addr ea;
35303531
int error;
3531-
35323532
error = netdev_get_etheraddr(port->up.netdev, &ea);
35333533
if (!error) {
35343534
struct dp_packet packet;
@@ -3607,6 +3607,9 @@ bundle_send_learning_packets(struct ofbundle *bundle)
36073607
static void
36083608
bundle_run(struct ofbundle *bundle)
36093609
{
3610+
if (bundle->lacp && ofproto_get_lacp_restore_wait()){
3611+
return;
3612+
}
36103613
if (bundle->lacp) {
36113614
lacp_run(bundle->lacp, send_pdu_cb);
36123615
}

ofproto/ofproto.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
325325

326326
/* The default value of true waits for flow restore. */
327327
static bool flow_restore_wait = true;
328+
/* The default value of true waits for lacp restore. */
329+
static bool lacp_restore_wait = true;
328330

329331
/* Must be called to initialize the ofproto library.
330332
*
@@ -988,6 +990,18 @@ ofproto_get_flow_restore_wait(void)
988990
return flow_restore_wait;
989991
}
990992

993+
void
994+
ofproto_set_lacp_restore_wait(bool lacp_restore_wait_db)
995+
{
996+
lacp_restore_wait = lacp_restore_wait_db;
997+
}
998+
999+
bool
1000+
ofproto_get_lacp_restore_wait(void)
1001+
{
1002+
return lacp_restore_wait;
1003+
}
1004+
9911005
/* Retrieve datapath capabilities. */
9921006
void
9931007
ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap)

ofproto/ofproto.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,8 @@ int ofproto_set_ipfix(struct ofproto *,
373373
size_t);
374374
void ofproto_set_flow_restore_wait(bool flow_restore_wait_db);
375375
bool ofproto_get_flow_restore_wait(void);
376+
void ofproto_set_lacp_restore_wait(bool lacp_restore_wait_db);
377+
bool ofproto_get_lacp_restore_wait(void);
376378
int ofproto_set_stp(struct ofproto *, const struct ofproto_stp_settings *);
377379
int ofproto_get_stp_status(struct ofproto *, struct ofproto_stp_status *);
378380

0 commit comments

Comments
 (0)