aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/datapath.c218
1 files changed, 110 insertions, 108 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index cb5d64a5c759..f3bcdac80bda 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1164,23 +1164,9 @@ error:
1164 return -EMSGSIZE; 1164 return -EMSGSIZE;
1165} 1165}
1166 1166
1167/* Must be called with ovs_mutex. */ 1167static struct sk_buff *ovs_dp_cmd_alloc_info(struct genl_info *info)
1168static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp,
1169 struct genl_info *info, u8 cmd)
1170{ 1168{
1171 struct sk_buff *skb; 1169 return genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL);
1172 int retval;
1173
1174 skb = genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL);
1175 if (!skb)
1176 return ERR_PTR(-ENOMEM);
1177
1178 retval = ovs_dp_cmd_fill_info(dp, skb, info->snd_portid, info->snd_seq, 0, cmd);
1179 if (retval < 0) {
1180 kfree_skb(skb);
1181 return ERR_PTR(retval);
1182 }
1183 return skb;
1184} 1170}
1185 1171
1186/* Called with rcu_read_lock or ovs_mutex. */ 1172/* Called with rcu_read_lock or ovs_mutex. */
@@ -1233,12 +1219,14 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1233 if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID]) 1219 if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID])
1234 goto err; 1220 goto err;
1235 1221
1236 ovs_lock(); 1222 reply = ovs_dp_cmd_alloc_info(info);
1223 if (!reply)
1224 return -ENOMEM;
1237 1225
1238 err = -ENOMEM; 1226 err = -ENOMEM;
1239 dp = kzalloc(sizeof(*dp), GFP_KERNEL); 1227 dp = kzalloc(sizeof(*dp), GFP_KERNEL);
1240 if (dp == NULL) 1228 if (dp == NULL)
1241 goto err_unlock_ovs; 1229 goto err_free_reply;
1242 1230
1243 ovs_dp_set_net(dp, hold_net(sock_net(skb->sk))); 1231 ovs_dp_set_net(dp, hold_net(sock_net(skb->sk)));
1244 1232
@@ -1273,6 +1261,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1273 1261
1274 ovs_dp_change(dp, a); 1262 ovs_dp_change(dp, a);
1275 1263
1264 /* So far only local changes have been made, now need the lock. */
1265 ovs_lock();
1266
1276 vport = new_vport(&parms); 1267 vport = new_vport(&parms);
1277 if (IS_ERR(vport)) { 1268 if (IS_ERR(vport)) {
1278 err = PTR_ERR(vport); 1269 err = PTR_ERR(vport);
@@ -1291,10 +1282,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1291 goto err_destroy_ports_array; 1282 goto err_destroy_ports_array;
1292 } 1283 }
1293 1284
1294 reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); 1285 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1295 err = PTR_ERR(reply); 1286 info->snd_seq, 0, OVS_DP_CMD_NEW);
1296 if (IS_ERR(reply)) 1287 BUG_ON(err < 0);
1297 goto err_destroy_local_port;
1298 1288
1299 ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); 1289 ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
1300 list_add_tail_rcu(&dp->list_node, &ovs_net->dps); 1290 list_add_tail_rcu(&dp->list_node, &ovs_net->dps);
@@ -1304,9 +1294,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1304 ovs_notify(&dp_datapath_genl_family, reply, info); 1294 ovs_notify(&dp_datapath_genl_family, reply, info);
1305 return 0; 1295 return 0;
1306 1296
1307err_destroy_local_port:
1308 ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
1309err_destroy_ports_array: 1297err_destroy_ports_array:
1298 ovs_unlock();
1310 kfree(dp->ports); 1299 kfree(dp->ports);
1311err_destroy_percpu: 1300err_destroy_percpu:
1312 free_percpu(dp->stats_percpu); 1301 free_percpu(dp->stats_percpu);
@@ -1315,8 +1304,8 @@ err_destroy_table:
1315err_free_dp: 1304err_free_dp:
1316 release_net(ovs_dp_get_net(dp)); 1305 release_net(ovs_dp_get_net(dp));
1317 kfree(dp); 1306 kfree(dp);
1318err_unlock_ovs: 1307err_free_reply:
1319 ovs_unlock(); 1308 kfree_skb(reply);
1320err: 1309err:
1321 return err; 1310 return err;
1322} 1311}
@@ -1354,16 +1343,19 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
1354 struct datapath *dp; 1343 struct datapath *dp;
1355 int err; 1344 int err;
1356 1345
1346 reply = ovs_dp_cmd_alloc_info(info);
1347 if (!reply)
1348 return -ENOMEM;
1349
1357 ovs_lock(); 1350 ovs_lock();
1358 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); 1351 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
1359 err = PTR_ERR(dp); 1352 err = PTR_ERR(dp);
1360 if (IS_ERR(dp)) 1353 if (IS_ERR(dp))
1361 goto unlock; 1354 goto err_unlock_free;
1362 1355
1363 reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_DEL); 1356 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1364 err = PTR_ERR(reply); 1357 info->snd_seq, 0, OVS_DP_CMD_DEL);
1365 if (IS_ERR(reply)) 1358 BUG_ON(err < 0);
1366 goto unlock;
1367 1359
1368 __dp_destroy(dp); 1360 __dp_destroy(dp);
1369 ovs_unlock(); 1361 ovs_unlock();
@@ -1371,8 +1363,10 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
1371 ovs_notify(&dp_datapath_genl_family, reply, info); 1363 ovs_notify(&dp_datapath_genl_family, reply, info);
1372 1364
1373 return 0; 1365 return 0;
1374unlock: 1366
1367err_unlock_free:
1375 ovs_unlock(); 1368 ovs_unlock();
1369 kfree_skb(reply);
1376 return err; 1370 return err;
1377} 1371}
1378 1372
@@ -1382,29 +1376,30 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
1382 struct datapath *dp; 1376 struct datapath *dp;
1383 int err; 1377 int err;
1384 1378
1379 reply = ovs_dp_cmd_alloc_info(info);
1380 if (!reply)
1381 return -ENOMEM;
1382
1385 ovs_lock(); 1383 ovs_lock();
1386 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); 1384 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
1387 err = PTR_ERR(dp); 1385 err = PTR_ERR(dp);
1388 if (IS_ERR(dp)) 1386 if (IS_ERR(dp))
1389 goto unlock; 1387 goto err_unlock_free;
1390 1388
1391 ovs_dp_change(dp, info->attrs); 1389 ovs_dp_change(dp, info->attrs);
1392 1390
1393 reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); 1391 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1394 if (IS_ERR(reply)) { 1392 info->snd_seq, 0, OVS_DP_CMD_NEW);
1395 err = PTR_ERR(reply); 1393 BUG_ON(err < 0);
1396 genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
1397 0, err);
1398 err = 0;
1399 goto unlock;
1400 }
1401 1394
1402 ovs_unlock(); 1395 ovs_unlock();
1403 ovs_notify(&dp_datapath_genl_family, reply, info); 1396 ovs_notify(&dp_datapath_genl_family, reply, info);
1404 1397
1405 return 0; 1398 return 0;
1406unlock: 1399
1400err_unlock_free:
1407 ovs_unlock(); 1401 ovs_unlock();
1402 kfree_skb(reply);
1408 return err; 1403 return err;
1409} 1404}
1410 1405
@@ -1414,24 +1409,26 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
1414 struct datapath *dp; 1409 struct datapath *dp;
1415 int err; 1410 int err;
1416 1411
1417 ovs_lock(); 1412 reply = ovs_dp_cmd_alloc_info(info);
1413 if (!reply)
1414 return -ENOMEM;
1415
1416 rcu_read_lock();
1418 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); 1417 dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
1419 if (IS_ERR(dp)) { 1418 if (IS_ERR(dp)) {
1420 err = PTR_ERR(dp); 1419 err = PTR_ERR(dp);
1421 goto unlock; 1420 goto err_unlock_free;
1422 }
1423
1424 reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
1425 if (IS_ERR(reply)) {
1426 err = PTR_ERR(reply);
1427 goto unlock;
1428 } 1421 }
1422 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1423 info->snd_seq, 0, OVS_DP_CMD_NEW);
1424 BUG_ON(err < 0);
1425 rcu_read_unlock();
1429 1426
1430 ovs_unlock();
1431 return genlmsg_reply(reply, info); 1427 return genlmsg_reply(reply, info);
1432 1428
1433unlock: 1429err_unlock_free:
1434 ovs_unlock(); 1430 rcu_read_unlock();
1431 kfree_skb(reply);
1435 return err; 1432 return err;
1436} 1433}
1437 1434
@@ -1544,7 +1541,12 @@ error:
1544 return err; 1541 return err;
1545} 1542}
1546 1543
1547/* Called with ovs_mutex or RCU read lock. */ 1544static struct sk_buff *ovs_vport_cmd_alloc_info(void)
1545{
1546 return nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1547}
1548
1549/* Called with ovs_mutex, only via ovs_dp_notify_wq(). */
1548struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid, 1550struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid,
1549 u32 seq, u8 cmd) 1551 u32 seq, u8 cmd)
1550{ 1552{
@@ -1606,33 +1608,35 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
1606 u32 port_no; 1608 u32 port_no;
1607 int err; 1609 int err;
1608 1610
1609 err = -EINVAL;
1610 if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] || 1611 if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] ||
1611 !a[OVS_VPORT_ATTR_UPCALL_PID]) 1612 !a[OVS_VPORT_ATTR_UPCALL_PID])
1612 goto exit; 1613 return -EINVAL;
1614
1615 port_no = a[OVS_VPORT_ATTR_PORT_NO]
1616 ? nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]) : 0;
1617 if (port_no >= DP_MAX_PORTS)
1618 return -EFBIG;
1619
1620 reply = ovs_vport_cmd_alloc_info();
1621 if (!reply)
1622 return -ENOMEM;
1613 1623
1614 ovs_lock(); 1624 ovs_lock();
1615 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 1625 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
1616 err = -ENODEV; 1626 err = -ENODEV;
1617 if (!dp) 1627 if (!dp)
1618 goto exit_unlock; 1628 goto exit_unlock_free;
1619
1620 if (a[OVS_VPORT_ATTR_PORT_NO]) {
1621 port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]);
1622
1623 err = -EFBIG;
1624 if (port_no >= DP_MAX_PORTS)
1625 goto exit_unlock;
1626 1629
1630 if (port_no) {
1627 vport = ovs_vport_ovsl(dp, port_no); 1631 vport = ovs_vport_ovsl(dp, port_no);
1628 err = -EBUSY; 1632 err = -EBUSY;
1629 if (vport) 1633 if (vport)
1630 goto exit_unlock; 1634 goto exit_unlock_free;
1631 } else { 1635 } else {
1632 for (port_no = 1; ; port_no++) { 1636 for (port_no = 1; ; port_no++) {
1633 if (port_no >= DP_MAX_PORTS) { 1637 if (port_no >= DP_MAX_PORTS) {
1634 err = -EFBIG; 1638 err = -EFBIG;
1635 goto exit_unlock; 1639 goto exit_unlock_free;
1636 } 1640 }
1637 vport = ovs_vport_ovsl(dp, port_no); 1641 vport = ovs_vport_ovsl(dp, port_no);
1638 if (!vport) 1642 if (!vport)
@@ -1650,22 +1654,19 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
1650 vport = new_vport(&parms); 1654 vport = new_vport(&parms);
1651 err = PTR_ERR(vport); 1655 err = PTR_ERR(vport);
1652 if (IS_ERR(vport)) 1656 if (IS_ERR(vport))
1653 goto exit_unlock; 1657 goto exit_unlock_free;
1654 1658
1655 err = 0; 1659 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
1656 reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq, 1660 info->snd_seq, 0, OVS_VPORT_CMD_NEW);
1657 OVS_VPORT_CMD_NEW); 1661 BUG_ON(err < 0);
1658 if (IS_ERR(reply)) { 1662 ovs_unlock();
1659 err = PTR_ERR(reply);
1660 ovs_dp_detach_port(vport);
1661 goto exit_unlock;
1662 }
1663 1663
1664 ovs_notify(&dp_vport_genl_family, reply, info); 1664 ovs_notify(&dp_vport_genl_family, reply, info);
1665 return 0;
1665 1666
1666exit_unlock: 1667exit_unlock_free:
1667 ovs_unlock(); 1668 ovs_unlock();
1668exit: 1669 kfree_skb(reply);
1669 return err; 1670 return err;
1670} 1671}
1671 1672
@@ -1676,28 +1677,26 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1676 struct vport *vport; 1677 struct vport *vport;
1677 int err; 1678 int err;
1678 1679
1680 reply = ovs_vport_cmd_alloc_info();
1681 if (!reply)
1682 return -ENOMEM;
1683
1679 ovs_lock(); 1684 ovs_lock();
1680 vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); 1685 vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
1681 err = PTR_ERR(vport); 1686 err = PTR_ERR(vport);
1682 if (IS_ERR(vport)) 1687 if (IS_ERR(vport))
1683 goto exit_unlock; 1688 goto exit_unlock_free;
1684 1689
1685 if (a[OVS_VPORT_ATTR_TYPE] && 1690 if (a[OVS_VPORT_ATTR_TYPE] &&
1686 nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) { 1691 nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) {
1687 err = -EINVAL; 1692 err = -EINVAL;
1688 goto exit_unlock; 1693 goto exit_unlock_free;
1689 }
1690
1691 reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1692 if (!reply) {
1693 err = -ENOMEM;
1694 goto exit_unlock;
1695 } 1694 }
1696 1695
1697 if (a[OVS_VPORT_ATTR_OPTIONS]) { 1696 if (a[OVS_VPORT_ATTR_OPTIONS]) {
1698 err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]); 1697 err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
1699 if (err) 1698 if (err)
1700 goto exit_free; 1699 goto exit_unlock_free;
1701 } 1700 }
1702 1701
1703 if (a[OVS_VPORT_ATTR_UPCALL_PID]) 1702 if (a[OVS_VPORT_ATTR_UPCALL_PID])
@@ -1711,10 +1710,9 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1711 ovs_notify(&dp_vport_genl_family, reply, info); 1710 ovs_notify(&dp_vport_genl_family, reply, info);
1712 return 0; 1711 return 0;
1713 1712
1714exit_free: 1713exit_unlock_free:
1715 kfree_skb(reply);
1716exit_unlock:
1717 ovs_unlock(); 1714 ovs_unlock();
1715 kfree_skb(reply);
1718 return err; 1716 return err;
1719} 1717}
1720 1718
@@ -1725,30 +1723,33 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
1725 struct vport *vport; 1723 struct vport *vport;
1726 int err; 1724 int err;
1727 1725
1726 reply = ovs_vport_cmd_alloc_info();
1727 if (!reply)
1728 return -ENOMEM;
1729
1728 ovs_lock(); 1730 ovs_lock();
1729 vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); 1731 vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
1730 err = PTR_ERR(vport); 1732 err = PTR_ERR(vport);
1731 if (IS_ERR(vport)) 1733 if (IS_ERR(vport))
1732 goto exit_unlock; 1734 goto exit_unlock_free;
1733 1735
1734 if (vport->port_no == OVSP_LOCAL) { 1736 if (vport->port_no == OVSP_LOCAL) {
1735 err = -EINVAL; 1737 err = -EINVAL;
1736 goto exit_unlock; 1738 goto exit_unlock_free;
1737 } 1739 }
1738 1740
1739 reply = ovs_vport_cmd_build_info(vport, info->snd_portid, 1741 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
1740 info->snd_seq, OVS_VPORT_CMD_DEL); 1742 info->snd_seq, 0, OVS_VPORT_CMD_DEL);
1741 err = PTR_ERR(reply); 1743 BUG_ON(err < 0);
1742 if (IS_ERR(reply))
1743 goto exit_unlock;
1744
1745 err = 0;
1746 ovs_dp_detach_port(vport); 1744 ovs_dp_detach_port(vport);
1745 ovs_unlock();
1747 1746
1748 ovs_notify(&dp_vport_genl_family, reply, info); 1747 ovs_notify(&dp_vport_genl_family, reply, info);
1748 return 0;
1749 1749
1750exit_unlock: 1750exit_unlock_free:
1751 ovs_unlock(); 1751 ovs_unlock();
1752 kfree_skb(reply);
1752 return err; 1753 return err;
1753} 1754}
1754 1755
@@ -1760,24 +1761,25 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
1760 struct vport *vport; 1761 struct vport *vport;
1761 int err; 1762 int err;
1762 1763
1764 reply = ovs_vport_cmd_alloc_info();
1765 if (!reply)
1766 return -ENOMEM;
1767
1763 rcu_read_lock(); 1768 rcu_read_lock();
1764 vport = lookup_vport(sock_net(skb->sk), ovs_header, a); 1769 vport = lookup_vport(sock_net(skb->sk), ovs_header, a);
1765 err = PTR_ERR(vport); 1770 err = PTR_ERR(vport);
1766 if (IS_ERR(vport)) 1771 if (IS_ERR(vport))
1767 goto exit_unlock; 1772 goto exit_unlock_free;
1768 1773 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
1769 reply = ovs_vport_cmd_build_info(vport, info->snd_portid, 1774 info->snd_seq, 0, OVS_VPORT_CMD_NEW);
1770 info->snd_seq, OVS_VPORT_CMD_NEW); 1775 BUG_ON(err < 0);
1771 err = PTR_ERR(reply);
1772 if (IS_ERR(reply))
1773 goto exit_unlock;
1774
1775 rcu_read_unlock(); 1776 rcu_read_unlock();
1776 1777
1777 return genlmsg_reply(reply, info); 1778 return genlmsg_reply(reply, info);
1778 1779
1779exit_unlock: 1780exit_unlock_free:
1780 rcu_read_unlock(); 1781 rcu_read_unlock();
1782 kfree_skb(reply);
1781 return err; 1783 return err;
1782} 1784}
1783 1785