@@ -168,6 +168,7 @@ static bool member_may_enable__(struct member *) OVS_REQUIRES(mutex);
168168
169169static unixctl_cb_func lacp_unixctl_show ;
170170static 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'. */
173174static 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
234237static 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+
943974static void
944975ds_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}
0 commit comments