Skip to content

Commit b4ab157

Browse files
committed
test lacp
1 parent 310fe32 commit b4ab157

File tree

7 files changed

+499
-4
lines changed

7 files changed

+499
-4
lines changed

lib/lacp.c

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "dp-packet.h"
2626
#include "ovs-atomic.h"
2727
#include "packets.h"
28+
#include "openvswitch/ofp-parse.h"
2829
#include "openvswitch/poll-loop.h"
2930
#include "seq.h"
3031
#include "openvswitch/shash.h"
@@ -168,6 +169,7 @@ static bool member_may_enable__(struct member *) OVS_REQUIRES(mutex);
168169

169170
static unixctl_cb_func lacp_unixctl_show;
170171
static unixctl_cb_func lacp_unixctl_show_stats;
172+
static unixctl_cb_func lacp_unixctl_set;
171173

172174
/* Populates 'pdu' with a LACP PDU comprised of 'actor' and 'partner'. */
173175
static void
@@ -229,6 +231,8 @@ lacp_init(void)
229231
lacp_unixctl_show, NULL);
230232
unixctl_command_register("lacp/show-stats", "[port]", 0, 1,
231233
lacp_unixctl_show_stats, NULL);
234+
unixctl_command_register("lacp/set", "[port]", 3, INT_MAX,
235+
lacp_unixctl_set, NULL);
232236
}
233237

234238
static void
@@ -940,6 +944,34 @@ lacp_find(const char *name) OVS_REQUIRES(mutex)
940944
return NULL;
941945
}
942946

947+
static struct member *
948+
lacp_member_find(struct lacp *lacp, const char *name) OVS_REQUIRES(mutex)
949+
{
950+
struct member *member;
951+
952+
HMAP_FOR_EACH_SAFE (member, node, &lacp->members) {
953+
if (!strcmp(member->name, name)) {
954+
return member;
955+
}
956+
}
957+
958+
return NULL;
959+
}
960+
961+
static struct member *
962+
lacp_member_find_by_key(struct lacp *lacp, uint16_t key) OVS_REQUIRES(mutex)
963+
{
964+
struct member *member;
965+
966+
HMAP_FOR_EACH_SAFE (member, node, &lacp->members) {
967+
if (member->port_id == key) {
968+
return member;
969+
}
970+
}
971+
972+
return NULL;
973+
}
974+
943975
static void
944976
ds_put_lacp_state(struct ds *ds, uint8_t state)
945977
{
@@ -1219,5 +1251,245 @@ lacp_get_member_stats(const struct lacp *lacp, const void *member_,
12191251
}
12201252
ovs_mutex_unlock(&mutex);
12211253
return ret;
1254+
}
1255+
1256+
static void
1257+
lacp_port_set(struct unixctl_conn *conn, struct lacp *lacp, const char *parms)
1258+
OVS_REQUIRES(mutex)
1259+
{
1260+
char *value;
1261+
char *key;
1262+
char **p = (char **)&parms;
1263+
while (ofputil_parse_key_value(p, &key, &value)) {
1264+
lacp->update = false;
1265+
uint32_t tmp;
1266+
if (nullable_string_is_equal(key, "status")) {
1267+
if (strstr(value, "active")) {
1268+
lacp->active = true;
1269+
}
1270+
if (strstr(value, "negotiated")) {
1271+
lacp->negotiated = true;
1272+
}
1273+
1274+
} else if (nullable_string_is_equal(key, "sys_id")) {
1275+
if (!eth_addr_from_string(value, &lacp->sys_id)) {
1276+
unixctl_command_reply_error(conn, "invalid port sys_id");
1277+
return;
1278+
}
1279+
} else if (nullable_string_is_equal(key, "sys_priority")) {
1280+
if (!str_to_uint(value, 10, &tmp)) {
1281+
unixctl_command_reply_error(conn, "invalid port sys_prority");
1282+
return;
1283+
}
1284+
lacp->sys_priority = tmp;
1285+
} else if (nullable_string_is_equal(key, "key")) {
1286+
if (!str_to_uint(value, 10, &tmp)) {
1287+
unixctl_command_reply_error(conn, "invalid port key");
1288+
return;
1289+
}
1290+
lacp->key_member = lacp_member_find_by_key(lacp, tmp);
1291+
}
1292+
}
1293+
}
1294+
1295+
static uint8_t
1296+
lacp_state_from_str(const char *s)
1297+
{
1298+
uint8_t state = 0;
1299+
if (strstr(s, "activity")) {
1300+
state |= LACP_STATE_ACT;
1301+
}
1302+
if (strstr(s, "timeout")) {
1303+
state |= LACP_STATE_TIME;
1304+
}
1305+
if (strstr(s, "aggregation")) {
1306+
state |= LACP_STATE_AGG;
1307+
}
1308+
if (strstr(s, "synchronized")) {
1309+
state |= LACP_STATE_SYNC;
1310+
}
1311+
if (strstr(s, "collecting")) {
1312+
state |= LACP_STATE_COL;
1313+
}
1314+
if (strstr(s, "distributing")) {
1315+
state |= LACP_STATE_DIST;
1316+
}
1317+
if (strstr(s, "defaulted")) {
1318+
state |= LACP_STATE_DEF;
1319+
}
1320+
if (strstr(s, "expired")) {
1321+
state |= LACP_STATE_EXP;
1322+
}
1323+
return state;
1324+
}
12221325

1326+
static void
1327+
lacp_member_set(struct unixctl_conn *conn, struct member *member,
1328+
const char *op, const char *parms) OVS_REQUIRES(mutex)
1329+
{
1330+
char *value;
1331+
char *key;
1332+
char **p = (char **)&parms;
1333+
if (nullable_string_is_equal(op, "member")) {
1334+
while (ofputil_parse_key_value(p, &key, &value)) {
1335+
uint32_t tmp;
1336+
if (nullable_string_is_equal(key, "port_id")) {
1337+
if (!str_to_uint(value, 10, &tmp)) {
1338+
unixctl_command_reply_error(conn, "invalid member "
1339+
"port_id");
1340+
return;
1341+
}
1342+
member->port_id = tmp;
1343+
} else if (nullable_string_is_equal(key, "port_priority")) {
1344+
if (!str_to_uint(value, 10, &tmp)) {
1345+
unixctl_command_reply_error(conn, "invalid member "
1346+
"port_priority");
1347+
return;
1348+
}
1349+
member->port_priority = tmp;
1350+
} else if (nullable_string_is_equal(key, "status")) {
1351+
if (strstr(value, "current")) {
1352+
member->status = LACP_CURRENT;
1353+
member->carrier_up = true;
1354+
} else if (strstr(value, "expired")) {
1355+
member->status = LACP_EXPIRED;
1356+
} else if (strstr(value, "defaulted")) {
1357+
member->status = LACP_DEFAULTED;
1358+
}
1359+
1360+
if (strstr(value, "attached")) {
1361+
member->attached = true;
1362+
}
1363+
}
1364+
}
1365+
} else if (nullable_string_is_equal(op, "actor")) {
1366+
while (ofputil_parse_key_value(p, &key, &value)) {
1367+
uint32_t tmp;
1368+
if (nullable_string_is_equal(key, "sys_id")) {
1369+
struct eth_addr addr;
1370+
if (!eth_addr_from_string(value, &addr)) {
1371+
unixctl_command_reply_error(conn, "invalid member "
1372+
"actor sys_id");
1373+
return;
1374+
}
1375+
member->ntt_actor.sys_id = addr;
1376+
} else if (nullable_string_is_equal(key, "sys_priority")) {
1377+
if (!str_to_uint(value, 10, &tmp)) {
1378+
unixctl_command_reply_error(conn, "invalid member "
1379+
"actor sys_priority");
1380+
return;
1381+
}
1382+
member->ntt_actor.sys_priority = htons(tmp);
1383+
} else if (nullable_string_is_equal(key, "port_id")) {
1384+
if (!str_to_uint(value, 10, &tmp)) {
1385+
unixctl_command_reply_error(conn, "invalid member "
1386+
"actor port_id");
1387+
return;
1388+
}
1389+
member->ntt_actor.port_id = htons(tmp);
1390+
} else if (nullable_string_is_equal(key, "port_priority")) {
1391+
if (!str_to_uint(value, 10, &tmp)) {
1392+
unixctl_command_reply_error(conn, "invalid member "
1393+
"actor port_priority");
1394+
return;
1395+
}
1396+
member->ntt_actor.port_priority = htons(tmp);
1397+
} else if (nullable_string_is_equal(key, "key")) {
1398+
if (!str_to_uint(value, 10, &tmp)) {
1399+
unixctl_command_reply_error(conn, "invalid member "
1400+
"actor key");
1401+
return;
1402+
}
1403+
member->ntt_actor.key = htons(tmp);
1404+
} else if (nullable_string_is_equal(key, "state")) {
1405+
member->ntt_actor.state = lacp_state_from_str(value);
1406+
VLOG_INFO("member->ntt_actor.state (%p) (%d)",
1407+
&(member->ntt_actor.state), member->ntt_actor.state);
1408+
}
1409+
}
1410+
} else if (nullable_string_is_equal(op, "partner")) {
1411+
while (ofputil_parse_key_value(p, &key, &value)) {
1412+
uint32_t tmp;
1413+
if (nullable_string_is_equal(key, "sys_id")) {
1414+
struct eth_addr addr;
1415+
if (!eth_addr_from_string(value, &addr)) {
1416+
unixctl_command_reply_error(conn, "invalid member "
1417+
"partner sys_id");
1418+
return;
1419+
}
1420+
member->partner.sys_id = addr;
1421+
} else if (nullable_string_is_equal(key, "sys_priority")) {
1422+
if (!str_to_uint(value, 10, &tmp)) {
1423+
unixctl_command_reply_error(conn, "invalid member "
1424+
"partner sys_priority");
1425+
return;
1426+
}
1427+
member->partner.sys_priority = htons(tmp);
1428+
} else if (nullable_string_is_equal(key, "port_id")) {
1429+
if (!str_to_uint(value, 10, &tmp)) {
1430+
unixctl_command_reply_error(conn, "invalid member "
1431+
"partner port_id");
1432+
return;
1433+
}
1434+
member->partner.port_id = htons(tmp);
1435+
} else if (nullable_string_is_equal(key, "port_priority")) {
1436+
if (!str_to_uint(value, 10, &tmp)) {
1437+
unixctl_command_reply_error(conn, "invalid member "
1438+
"partner port_priority");
1439+
return;
1440+
}
1441+
member->partner.port_priority = htons(tmp);
1442+
} else if (nullable_string_is_equal(key, "key")) {
1443+
if (!str_to_uint(value, 10, &tmp)) {
1444+
unixctl_command_reply_error(conn, "invalid member "
1445+
"partner key");
1446+
return;
1447+
}
1448+
member->partner.key = htons(tmp);
1449+
} else if (nullable_string_is_equal(key, "state")) {
1450+
member->partner.state = lacp_state_from_str(value);
1451+
}
1452+
}
1453+
} else {
1454+
unixctl_command_reply_error(conn, "invalid member op");
1455+
}
1456+
timer_set_duration(&member->tx, LACP_FAST_TIME_TX);
1457+
timer_set_duration(&member->rx, LACP_FAST_TIME_TX);
1458+
}
1459+
1460+
static void
1461+
lacp_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
1462+
void *aux OVS_UNUSED) OVS_EXCLUDED(mutex)
1463+
{
1464+
struct member *member;
1465+
struct lacp *lacp;
1466+
1467+
lacp_lock();
1468+
lacp = lacp_find(argv[1]);
1469+
if (!lacp) {
1470+
unixctl_command_reply_error(conn, "lacp port not found");
1471+
goto out;
1472+
}
1473+
1474+
if (nullable_string_is_equal(argv[2], "port")) {
1475+
lacp_port_set(conn, lacp, argv[3]);
1476+
} else if (nullable_string_is_equal(argv[2], "member")) {
1477+
member = lacp_member_find(lacp, argv[3]);
1478+
if (!member) {
1479+
unixctl_command_reply_error(conn, "lacp member not found");
1480+
goto out;
1481+
}
1482+
if (argc < 5) {
1483+
unixctl_command_reply_error(conn, "invalid member parms");
1484+
goto out;
1485+
}
1486+
lacp_member_set(conn, member, argv[4], argv[5]);
1487+
} else {
1488+
unixctl_command_reply_error(conn, "invalid op type");
1489+
goto out;
1490+
}
1491+
1492+
out:
1493+
unixctl_command_reply(conn, NULL);
1494+
lacp_unlock();
12231495
}

ofproto/ofproto-dpif.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "nx-match.h"
4242
#include "odp-util.h"
4343
#include "odp-execute.h"
44+
#include "ofproto/ofproto.h"
4445
#include "ofproto/ofproto-dpif.h"
4546
#include "ofproto/ofproto-provider.h"
4647
#include "ofproto-dpif-ipfix.h"
@@ -3702,7 +3703,6 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size)
37023703
struct ofport_dpif *port = port_;
37033704
struct eth_addr ea;
37043705
int error;
3705-
37063706
error = netdev_get_etheraddr(port->up.netdev, &ea);
37073707
if (!error) {
37083708
struct dp_packet packet;
@@ -3781,6 +3781,9 @@ bundle_send_learning_packets(struct ofbundle *bundle)
37813781
static void
37823782
bundle_run(struct ofbundle *bundle)
37833783
{
3784+
if (bundle->lacp && ofproto_get_lacp_restore_wait()){
3785+
return;
3786+
}
37843787
if (bundle->lacp) {
37853788
lacp_run(bundle->lacp, send_pdu_cb);
37863789
}

ofproto/ofproto.c

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

327327
/* The default value of true waits for flow restore. */
328328
static bool flow_restore_wait = true;
329+
/* The default value of true waits for lacp restore. */
330+
static bool lacp_restore_wait = true;
329331

330332
/* Must be called to initialize the ofproto library.
331333
*
@@ -997,6 +999,18 @@ ofproto_get_flow_restore_wait(void)
997999
return flow_restore_wait;
9981000
}
9991001

1002+
void
1003+
ofproto_set_lacp_restore_wait(bool lacp_restore_wait_db)
1004+
{
1005+
lacp_restore_wait = lacp_restore_wait_db;
1006+
}
1007+
1008+
bool
1009+
ofproto_get_lacp_restore_wait(void)
1010+
{
1011+
return lacp_restore_wait;
1012+
}
1013+
10001014
/* Retrieve datapath capabilities. */
10011015
void
10021016
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
@@ -382,6 +382,8 @@ int ofproto_set_local_sample(struct ofproto *ofproto,
382382
size_t n_options);
383383
void ofproto_set_flow_restore_wait(bool flow_restore_wait_db);
384384
bool ofproto_get_flow_restore_wait(void);
385+
void ofproto_set_lacp_restore_wait(bool lacp_restore_wait_db);
386+
bool ofproto_get_lacp_restore_wait(void);
385387
int ofproto_set_stp(struct ofproto *, const struct ofproto_stp_settings *);
386388
int ofproto_get_stp_status(struct ofproto *, struct ofproto_stp_status *);
387389

0 commit comments

Comments
 (0)