705 struct netdev_solaris *netdev = xzalloc(sizeof (*netdev)); |
714 struct netdev_solaris *netdev = xzalloc(sizeof (*netdev)); |
706 |
715 |
707 return (&netdev->up); |
716 return (&netdev->up); |
708 } |
717 } |
709 |
718 |
|
719 static void |
|
720 netdev_solaris_add_port_to_bridge_mapping(const struct netdev |
|
721 *netdev, const char *brname) |
|
722 { |
|
723 VLOG_DBG("netdev_solaris_add_port_to_bridge_mapping: adding a mapping " |
|
724 "<%s,%s> to port_to_bridge_map", netdev->name, brname); |
|
725 shash_add_nocopy(&port_to_bridge_map, netdev->name, brname); |
|
726 } |
|
727 |
710 static int |
728 static int |
711 netdev_solaris_unconfigure_uplink(const struct netdev *netdev_) |
729 netdev_solaris_unconfigure_uplink(const struct netdev *netdev_) |
712 { |
730 { |
713 struct netdev_solaris *netdev = netdev_solaris_cast(netdev_); |
731 struct netdev_solaris *netdev = netdev_solaris_cast(netdev_); |
714 const char *netdev_name = netdev_get_name(netdev_); |
732 const char *netdev_name = netdev_get_name(netdev_); |
715 int error; |
733 int error; |
|
734 char curr_lower[DLADM_PROP_VAL_MAX]; |
|
735 struct netdev *netdev_to_migrate = NULL; |
|
736 char *new_lower = NULL; |
|
737 bool b_error = false; |
716 |
738 |
717 VLOG_DBG("netdev_solaris_unconfigure_uplink device %s", netdev_name); |
739 VLOG_DBG("netdev_solaris_unconfigure_uplink device %s", netdev_name); |
718 |
740 |
719 error = solaris_modify_vnic(NETDEV_IMPL_ETHERSTUB, netdev->brname); |
741 error = solaris_get_dlprop(netdev->brname, "lower-link", "current", |
720 if (error != 0 && error != ENODEV) { |
742 curr_lower, sizeof (curr_lower)); |
721 VLOG_ERR("failed to unconfigure %s as uplink for %s: " |
743 if (error) { |
722 "%s", netdev_name, netdev->brname, |
744 VLOG_ERR("netdev_solaris_unconfigure_uplink couldn't obtain " |
723 ovs_strerror(error)); |
745 "bridge(%s) lowerlink", netdev->brname); |
|
746 return (0); |
|
747 } |
|
748 |
|
749 if (strcmp(netdev_name, curr_lower) == 0) { |
|
750 /* |
|
751 * The uplink which we are trying to remove has bridge vnic on |
|
752 * top of it. We need to migrate bridge vnic to a different |
|
753 * uplink or to ovs.etherstub0 if uplink_port_list is empty. |
|
754 */ |
|
755 VLOG_DBG("netdev_solaris_unconfigure_uplink: unconfiguring the " |
|
756 "uplink (%s) which is the bridge %s's lowerlink (%s)", |
|
757 netdev_name, netdev->brname, curr_lower); |
|
758 |
|
759 netdev_to_migrate = dpif_solaris_obtain_netdev_to_migrate( |
|
760 netdev->brname, &b_error); |
|
761 if (b_error) { |
|
762 VLOG_ERR("netdev_solaris_unconfigure_uplink: couldn't " |
|
763 "obtain netdev_to_migrate for bridge vnic %s", |
|
764 netdev->brname); |
|
765 return (0); |
|
766 } |
|
767 |
|
768 if (netdev_to_migrate == NULL) |
|
769 new_lower = NETDEV_IMPL_ETHERSTUB; |
|
770 else |
|
771 new_lower = netdev_to_migrate->name; |
|
772 |
|
773 VLOG_DBG("netdev_solaris_unconfigure_uplink migrating bridge " |
|
774 "vnic to %s", new_lower); |
|
775 |
|
776 error = solaris_modify_vnic(new_lower, netdev->brname); |
|
777 if (error != 0) { |
|
778 VLOG_ERR("failed to unconfigure %s as uplink for %s: " |
|
779 "%s", netdev_name, netdev->brname, |
|
780 ovs_strerror(error)); |
|
781 return (0); |
|
782 } |
|
783 |
|
784 /* |
|
785 * reset internal port's physname and refresh its port channel. |
|
786 */ |
|
787 dpif_solaris_migrate_internal_port(netdev->brname, new_lower); |
724 } |
788 } |
725 return (0); |
789 return (0); |
726 } |
790 } |
727 |
791 |
728 static int |
792 static int |
729 netdev_solaris_configure_uplink(const struct netdev *netdev_, |
793 netdev_solaris_configure_uplink(const struct netdev *netdev_, |
730 const char *brname) |
794 const char *brname) |
731 { |
795 { |
732 struct netdev_solaris *netdev = netdev_solaris_cast(netdev_); |
796 struct netdev_solaris *netdev = netdev_solaris_cast(netdev_); |
733 const char *netdev_name = netdev_get_name(netdev_); |
797 const char *new_uplink = netdev_get_name(netdev_); |
734 char buffer[DLADM_PROP_VAL_MAX]; |
798 char curr_lower[DLADM_PROP_VAL_MAX]; |
735 int error; |
799 int error; |
736 |
800 const char *netdev_existing_class; |
737 VLOG_DBG("netdev_solaris_configure_uplink device %s", netdev_name); |
801 struct netdev *i_netdev; |
|
802 boolean_t migrated = B_FALSE; |
|
803 |
|
804 VLOG_DBG("netdev_solaris_configure_uplink device %s", new_uplink); |
738 |
805 |
739 /* |
806 /* |
740 * Normally, we would expect to see that the bridge VNIC has already |
807 * Normally, we would expect to see that the bridge VNIC has already |
741 * been created by a call to netdev_solaris_construct() to create the |
808 * been created by a call to netdev_solaris_construct() to create the |
742 * bridge netdev. However, on a service restart ovs-vswitchd sometimes |
809 * bridge netdev. However, on a service restart ovs-vswitchd sometimes |
743 * adds the lower-link port prior to adding the bridge's internal port. |
810 * adds the lower-link port prior to adding the bridge's internal port. |
744 * As a result, we need to create the bridge VNIC here if it does not |
811 * As a result, we need to create the bridge VNIC here if it does not |
745 * already exist. |
812 * already exist. |
746 */ |
813 */ |
747 error = solaris_get_dlprop(brname, "lower-link", "current", |
814 error = solaris_get_dlprop(brname, "lower-link", "current", |
748 buffer, sizeof (buffer)); |
815 curr_lower, sizeof (curr_lower)); |
|
816 VLOG_DBG("netdev_solaris_configure_uplink lower-link:%s", curr_lower); |
|
817 |
749 if (error == ENODEV) { |
818 if (error == ENODEV) { |
750 VLOG_DBG("%s vnic being created on %s", |
819 /* |
751 brname, netdev_name); |
820 * No implicit VNIC being created yet, create it now |
752 error = solaris_create_vnic(netdev_name, brname); |
821 */ |
753 if (error != 0) { |
822 VLOG_DBG("%s vnic being created on %s", brname, new_uplink); |
|
823 error = solaris_create_vnic(new_uplink, brname); |
|
824 if (error == 0) { |
|
825 (void) strlcpy(netdev->brname, brname, |
|
826 sizeof (netdev->brname)); |
|
827 } else { |
754 VLOG_ERR("Failed to create vnic for %s: %s", |
828 VLOG_ERR("Failed to create vnic for %s: %s", |
755 brname, ovs_strerror(error)); |
829 brname, ovs_strerror(error)); |
756 } |
830 } |
757 goto exit; |
831 goto exit; |
758 } else if (error != 0) { |
832 } else if (error != 0) { |
763 |
837 |
764 /* |
838 /* |
765 * If the lower-link is already set correctly, then return with |
839 * If the lower-link is already set correctly, then return with |
766 * success. |
840 * success. |
767 */ |
841 */ |
768 if (strcmp(buffer, netdev_name) == 0) { |
842 if (strcmp(curr_lower, new_uplink) == 0) { |
|
843 VLOG_DBG("netdev_solaris_configure_uplink lower-link(%s) is " |
|
844 "already correctly set. (%s)", curr_lower, new_uplink); |
769 error = 0; |
845 error = 0; |
770 goto exit; |
846 goto exit; |
771 } |
847 } |
772 |
848 |
773 /* |
849 if (strcmp(curr_lower, NETDEV_IMPL_ETHERSTUB) == 0) { |
774 * If the lower-link is already set to something other than the |
850 /* |
775 * etherstub, something is wrong. |
851 * Bridge vnic is on ovs.etherstub0. We have to migrate the |
776 */ |
852 * bridge vnic to the uplink |
777 if (strcmp(buffer, NETDEV_IMPL_ETHERSTUB) != 0) { |
853 */ |
778 VLOG_ERR("Bridge already has uplink %s", buffer); |
854 VLOG_DBG("bridge vnic %s is on %s, migrating it to %s", |
779 error = EEXIST; |
855 brname, curr_lower, new_uplink); |
780 goto exit; |
856 |
781 } |
857 error = solaris_modify_vnic(new_uplink, brname); |
782 |
858 if (error != 0) { |
783 /* |
859 VLOG_ERR("failed to configure %s as uplink: %s", |
784 * This is the "normal" case, where the bridge VNIC existed and had |
860 new_uplink, ovs_strerror(error)); |
785 * the etherstub as its lower-link. Move the VNIC to its uplink. |
861 goto exit; |
786 */ |
862 } |
787 error = solaris_modify_vnic(netdev_name, brname); |
863 migrated = B_TRUE; |
788 if (error != 0) { |
864 } else { |
789 VLOG_ERR("failed to configure %s as uplink: %s", |
865 /* |
790 netdev_name, ovs_strerror(error)); |
866 * Bridge vnic is already on an uplink. Now we see if the |
791 goto exit; |
867 * uplink to be added is other than etherstub or not. |
|
868 * If the bridge vnic is currently residing on an etherstub |
|
869 * and the one to be configured is not etherstub, |
|
870 * then we migrate the bridge vnic. |
|
871 */ |
|
872 i_netdev = netdev_from_name(curr_lower); |
|
873 if (!i_netdev) { |
|
874 VLOG_ERR("netdev_solaris_configure_uplink error " |
|
875 "in fetching lower-link netdev for %s", curr_lower); |
|
876 goto exit; |
|
877 } |
|
878 /* i_netdev->ref_cnt--; */ |
|
879 netdev_close(i_netdev); |
|
880 |
|
881 netdev_existing_class = netdev_solaris_get_class(i_netdev); |
|
882 if ((strcmp(netdev_existing_class, "etherstub") == 0) && |
|
883 (strcmp(netdev->class, "etherstub") != 0)) { |
|
884 error = solaris_modify_vnic(new_uplink, brname); |
|
885 if (error != 0) { |
|
886 VLOG_ERR("failed to configure %s as uplink: %s", |
|
887 new_uplink, ovs_strerror(error)); |
|
888 goto exit; |
|
889 } |
|
890 migrated = B_TRUE; |
|
891 } |
792 } |
892 } |
793 (void) strlcpy(netdev->brname, brname, sizeof (netdev->brname)); |
893 (void) strlcpy(netdev->brname, brname, sizeof (netdev->brname)); |
794 |
894 |
795 exit: |
895 exit: |
|
896 /* |
|
897 * reset internal port's physname and refresh its port channel. |
|
898 */ |
|
899 if (migrated) |
|
900 dpif_solaris_migrate_internal_port(brname, new_uplink); |
796 return (error); |
901 return (error); |
797 } |
902 } |
798 |
903 |
799 static boolean_t |
904 static boolean_t |
800 solaris_is_if_plumbed(struct netdev *netdev_, sa_family_t af, uint64_t *flags) |
905 solaris_is_if_plumbed(struct netdev *netdev_, sa_family_t af, uint64_t *flags) |