+ xbridge->support = *support;
+}
+
+static void
+xlate_xbundle_set(struct xbundle *xbundle,
+ enum port_vlan_mode vlan_mode, int vlan,
+ unsigned long *trunks, bool use_priority_tags,
+ const struct bond *bond, const struct lacp *lacp,
+ bool floodable)
+{
+ ovs_assert(xbundle->xbridge);
+
+ xbundle->vlan_mode = vlan_mode;
+ xbundle->vlan = vlan;
+ xbundle->trunks = trunks;
+ xbundle->use_priority_tags = use_priority_tags;
+ xbundle->floodable = floodable;
+
+ if (xbundle->bond != bond) {
+ bond_unref(xbundle->bond);
+ xbundle->bond = bond_ref(bond);
+ }
+
+ if (xbundle->lacp != lacp) {
+ lacp_unref(xbundle->lacp);
+ xbundle->lacp = lacp_ref(lacp);
+ }
+}
+
+static void
+xlate_xport_set(struct xport *xport, odp_port_t odp_port,
+ const struct netdev *netdev, const struct cfm *cfm,
+ const struct bfd *bfd, const struct lldp *lldp, int stp_port_no,
+ const struct rstp_port* rstp_port,
+ enum ofputil_port_config config, enum ofputil_port_state state,
+ bool is_tunnel, bool may_enable)
+{
+ xport->config = config;
+ xport->state = state;
+ xport->stp_port_no = stp_port_no;
+ xport->is_tunnel = is_tunnel;
+ xport->may_enable = may_enable;
+ xport->odp_port = odp_port;
+
+ if (xport->rstp_port != rstp_port) {
+ rstp_port_unref(xport->rstp_port);
+ xport->rstp_port = rstp_port_ref(rstp_port);
+ }
+
+ if (xport->cfm != cfm) {
+ cfm_unref(xport->cfm);
+ xport->cfm = cfm_ref(cfm);
+ }
+
+ if (xport->bfd != bfd) {
+ bfd_unref(xport->bfd);
+ xport->bfd = bfd_ref(bfd);
+ }
+
+ if (xport->lldp != lldp) {
+ lldp_unref(xport->lldp);
+ xport->lldp = lldp_ref(lldp);
+ }
+
+ if (xport->netdev != netdev) {
+ netdev_close(xport->netdev);
+ xport->netdev = netdev_ref(netdev);
+ }
+}
+
+static void
+xlate_xbridge_copy(struct xbridge *xbridge)
+{
+ struct xbundle *xbundle;
+ struct xport *xport;
+ struct xbridge *new_xbridge = xzalloc(sizeof *xbridge);
+ new_xbridge->ofproto = xbridge->ofproto;
+ new_xbridge->name = xstrdup(xbridge->name);
+ xlate_xbridge_init(new_xcfg, new_xbridge);
+
+ xlate_xbridge_set(new_xbridge,
+ xbridge->dpif, xbridge->ml, xbridge->stp,
+ xbridge->rstp, xbridge->ms, xbridge->mbridge,
+ xbridge->sflow, xbridge->ipfix, xbridge->netflow,
+ xbridge->forward_bpdu, xbridge->has_in_band,
+ &xbridge->support);
+ LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) {
+ xlate_xbundle_copy(new_xbridge, xbundle);
+ }
+
+ /* Copy xports which are not part of a xbundle */
+ HMAP_FOR_EACH (xport, ofp_node, &xbridge->xports) {
+ if (!xport->xbundle) {
+ xlate_xport_copy(new_xbridge, NULL, xport);
+ }
+ }
+}
+
+static void
+xlate_xbundle_copy(struct xbridge *xbridge, struct xbundle *xbundle)
+{
+ struct xport *xport;
+ struct xbundle *new_xbundle = xzalloc(sizeof *xbundle);
+ new_xbundle->ofbundle = xbundle->ofbundle;
+ new_xbundle->xbridge = xbridge;
+ new_xbundle->name = xstrdup(xbundle->name);
+ xlate_xbundle_init(new_xcfg, new_xbundle);
+
+ xlate_xbundle_set(new_xbundle, xbundle->vlan_mode,
+ xbundle->vlan, xbundle->trunks,
+ xbundle->use_priority_tags, xbundle->bond, xbundle->lacp,
+ xbundle->floodable);
+ LIST_FOR_EACH (xport, bundle_node, &xbundle->xports) {
+ xlate_xport_copy(xbridge, new_xbundle, xport);
+ }
+}
+
+static void
+xlate_xport_copy(struct xbridge *xbridge, struct xbundle *xbundle,
+ struct xport *xport)
+{
+ struct skb_priority_to_dscp *pdscp, *new_pdscp;
+ struct xport *new_xport = xzalloc(sizeof *xport);
+ new_xport->ofport = xport->ofport;
+ new_xport->ofp_port = xport->ofp_port;
+ new_xport->xbridge = xbridge;
+ xlate_xport_init(new_xcfg, new_xport);
+
+ xlate_xport_set(new_xport, xport->odp_port, xport->netdev, xport->cfm,
+ xport->bfd, xport->lldp, xport->stp_port_no,
+ xport->rstp_port, xport->config, xport->state,
+ xport->is_tunnel, xport->may_enable);
+
+ if (xport->peer) {
+ struct xport *peer = xport_lookup(new_xcfg, xport->peer->ofport);
+ if (peer) {
+ new_xport->peer = peer;
+ new_xport->peer->peer = new_xport;
+ }
+ }
+
+ if (xbundle) {
+ new_xport->xbundle = xbundle;
+ list_insert(&new_xport->xbundle->xports, &new_xport->bundle_node);
+ }
+
+ HMAP_FOR_EACH (pdscp, hmap_node, &xport->skb_priorities) {
+ new_pdscp = xmalloc(sizeof *pdscp);
+ new_pdscp->skb_priority = pdscp->skb_priority;
+ new_pdscp->dscp = pdscp->dscp;
+ hmap_insert(&new_xport->skb_priorities, &new_pdscp->hmap_node,
+ hash_int(new_pdscp->skb_priority, 0));
+ }