#define HNS_ROCE_VLAN_SL_BIT_MASK      7
 #define HNS_ROCE_VLAN_SL_SHIFT         13
 
+static inline u16 get_ah_udp_sport(const struct rdma_ah_attr *ah_attr)
+{
+       u32 fl = ah_attr->grh.flow_label;
+       u16 sport;
+
+       if (!fl)
+               sport = get_random_u32() %
+                       (IB_ROCE_UDP_ENCAP_VALID_PORT_MAX + 1 -
+                        IB_ROCE_UDP_ENCAP_VALID_PORT_MIN) +
+                       IB_ROCE_UDP_ENCAP_VALID_PORT_MIN;
+       else
+               sport = rdma_flow_label_to_udp_sport(fl);
+
+       return sport;
+}
+
 int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
                       struct ib_udata *udata)
 {
 
        memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE);
        ah->av.sl = rdma_ah_get_sl(ah_attr);
+       ah->av.flowlabel = grh->flow_label;
+       ah->av.udp_sport = get_ah_udp_sport(ah_attr);
 
        return 0;
 }
 
                       curr_idx & (qp->sge.sge_cnt - 1));
 
        roce_set_field(ud_sq_wqe->byte_24, V2_UD_SEND_WQE_BYTE_24_UDPSPN_M,
-                      V2_UD_SEND_WQE_BYTE_24_UDPSPN_S, 0);
+                      V2_UD_SEND_WQE_BYTE_24_UDPSPN_S, ah->av.udp_sport);
        ud_sq_wqe->qkey = cpu_to_le32(ud_wr(wr)->remote_qkey & 0x80000000 ?
                          qp->qkey : ud_wr(wr)->remote_qkey);
        roce_set_field(ud_sq_wqe->byte_32, V2_UD_SEND_WQE_BYTE_32_DQPN_M,
        return 0;
 }
 
+static inline u16 get_udp_sport(u32 fl, u32 lqpn, u32 rqpn)
+{
+       if (!fl)
+               fl = rdma_calc_flow_label(lqpn, rqpn);
+
+       return rdma_flow_label_to_udp_sport(fl);
+}
+
 static int hns_roce_v2_set_path(struct ib_qp *ibqp,
                                const struct ib_qp_attr *attr,
                                int attr_mask,
 
        roce_set_field(context->byte_52_udpspn_dmac, V2_QPC_BYTE_52_UDPSPN_M,
                       V2_QPC_BYTE_52_UDPSPN_S,
-                      is_udp ? 0x12b7 : 0);
+                      is_udp ? get_udp_sport(grh->flow_label, ibqp->qp_num,
+                                             attr->dest_qp_num) : 0);
 
        roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_UDPSPN_M,
                       V2_QPC_BYTE_52_UDPSPN_S, 0);