Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
0003  * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
0004  * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
0005  * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
0006  * Copyright (c) 2004-2007 Voltaire Corporation.  All rights reserved.
0007  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0008  * Copyright (c) 2014 Intel Corporation.  All rights reserved.
0009  *
0010  * This software is available to you under a choice of one of two
0011  * licenses.  You may choose to be licensed under the terms of the GNU
0012  * General Public License (GPL) Version 2, available from the file
0013  * COPYING in the main directory of this source tree, or the
0014  * OpenIB.org BSD license below:
0015  *
0016  *     Redistribution and use in source and binary forms, with or
0017  *     without modification, are permitted provided that the following
0018  *     conditions are met:
0019  *
0020  *      - Redistributions of source code must retain the above
0021  *        copyright notice, this list of conditions and the following
0022  *        disclaimer.
0023  *
0024  *      - Redistributions in binary form must reproduce the above
0025  *        copyright notice, this list of conditions and the following
0026  *        disclaimer in the documentation and/or other materials
0027  *        provided with the distribution.
0028  *
0029  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0030  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0031  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0032  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0033  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0034  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0035  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0036  * SOFTWARE.
0037  *
0038  */
0039 
0040 #include <rdma/ib_smi.h>
0041 #include "smi.h"
0042 #include "opa_smi.h"
0043 
0044 static enum smi_action __smi_handle_dr_smp_send(bool is_switch, u32 port_num,
0045                         u8 *hop_ptr, u8 hop_cnt,
0046                         const u8 *initial_path,
0047                         const u8 *return_path,
0048                         u8 direction,
0049                         bool dr_dlid_is_permissive,
0050                         bool dr_slid_is_permissive)
0051 {
0052     /* See section 14.2.2.2, Vol 1 IB spec */
0053     /* C14-6 -- valid hop_cnt values are from 0 to 63 */
0054     if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
0055         return IB_SMI_DISCARD;
0056 
0057     if (!direction) {
0058         /* C14-9:1 */
0059         if (hop_cnt && *hop_ptr == 0) {
0060             (*hop_ptr)++;
0061             return (initial_path[*hop_ptr] ==
0062                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0063         }
0064 
0065         /* C14-9:2 */
0066         if (*hop_ptr && *hop_ptr < hop_cnt) {
0067             if (!is_switch)
0068                 return IB_SMI_DISCARD;
0069 
0070             /* return_path set when received */
0071             (*hop_ptr)++;
0072             return (initial_path[*hop_ptr] ==
0073                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0074         }
0075 
0076         /* C14-9:3 -- We're at the end of the DR segment of path */
0077         if (*hop_ptr == hop_cnt) {
0078             /* return_path set when received */
0079             (*hop_ptr)++;
0080             return (is_switch ||
0081                 dr_dlid_is_permissive ?
0082                 IB_SMI_HANDLE : IB_SMI_DISCARD);
0083         }
0084 
0085         /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
0086         /* C14-9:5 -- Fail unreasonable hop pointer */
0087         return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0088 
0089     } else {
0090         /* C14-13:1 */
0091         if (hop_cnt && *hop_ptr == hop_cnt + 1) {
0092             (*hop_ptr)--;
0093             return (return_path[*hop_ptr] ==
0094                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0095         }
0096 
0097         /* C14-13:2 */
0098         if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
0099             if (!is_switch)
0100                 return IB_SMI_DISCARD;
0101 
0102             (*hop_ptr)--;
0103             return (return_path[*hop_ptr] ==
0104                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0105         }
0106 
0107         /* C14-13:3 -- at the end of the DR segment of path */
0108         if (*hop_ptr == 1) {
0109             (*hop_ptr)--;
0110             /* C14-13:3 -- SMPs destined for SM shouldn't be here */
0111             return (is_switch ||
0112                 dr_slid_is_permissive ?
0113                 IB_SMI_HANDLE : IB_SMI_DISCARD);
0114         }
0115 
0116         /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
0117         if (*hop_ptr == 0)
0118             return IB_SMI_HANDLE;
0119 
0120         /* C14-13:5 -- Check for unreasonable hop pointer */
0121         return IB_SMI_DISCARD;
0122     }
0123 }
0124 
0125 /*
0126  * Fixup a directed route SMP for sending
0127  * Return IB_SMI_DISCARD if the SMP should be discarded
0128  */
0129 enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
0130                        bool is_switch, u32 port_num)
0131 {
0132     return __smi_handle_dr_smp_send(is_switch, port_num,
0133                     &smp->hop_ptr, smp->hop_cnt,
0134                     smp->initial_path,
0135                     smp->return_path,
0136                     ib_get_smp_direction(smp),
0137                     smp->dr_dlid == IB_LID_PERMISSIVE,
0138                     smp->dr_slid == IB_LID_PERMISSIVE);
0139 }
0140 
0141 enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
0142                        bool is_switch, u32 port_num)
0143 {
0144     return __smi_handle_dr_smp_send(is_switch, port_num,
0145                     &smp->hop_ptr, smp->hop_cnt,
0146                     smp->route.dr.initial_path,
0147                     smp->route.dr.return_path,
0148                     opa_get_smp_direction(smp),
0149                     smp->route.dr.dr_dlid ==
0150                     OPA_LID_PERMISSIVE,
0151                     smp->route.dr.dr_slid ==
0152                     OPA_LID_PERMISSIVE);
0153 }
0154 
0155 static enum smi_action __smi_handle_dr_smp_recv(bool is_switch, u32 port_num,
0156                         int phys_port_cnt,
0157                         u8 *hop_ptr, u8 hop_cnt,
0158                         const u8 *initial_path,
0159                         u8 *return_path,
0160                         u8 direction,
0161                         bool dr_dlid_is_permissive,
0162                         bool dr_slid_is_permissive)
0163 {
0164     /* See section 14.2.2.2, Vol 1 IB spec */
0165     /* C14-6 -- valid hop_cnt values are from 0 to 63 */
0166     if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
0167         return IB_SMI_DISCARD;
0168 
0169     if (!direction) {
0170         /* C14-9:1 -- sender should have incremented hop_ptr */
0171         if (hop_cnt && *hop_ptr == 0)
0172             return IB_SMI_DISCARD;
0173 
0174         /* C14-9:2 -- intermediate hop */
0175         if (*hop_ptr && *hop_ptr < hop_cnt) {
0176             if (!is_switch)
0177                 return IB_SMI_DISCARD;
0178 
0179             return_path[*hop_ptr] = port_num;
0180             /* hop_ptr updated when sending */
0181             return (initial_path[*hop_ptr+1] <= phys_port_cnt ?
0182                 IB_SMI_HANDLE : IB_SMI_DISCARD);
0183         }
0184 
0185         /* C14-9:3 -- We're at the end of the DR segment of path */
0186         if (*hop_ptr == hop_cnt) {
0187             if (hop_cnt)
0188                 return_path[*hop_ptr] = port_num;
0189             /* hop_ptr updated when sending */
0190 
0191             return (is_switch ||
0192                 dr_dlid_is_permissive ?
0193                 IB_SMI_HANDLE : IB_SMI_DISCARD);
0194         }
0195 
0196         /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
0197         /* C14-9:5 -- fail unreasonable hop pointer */
0198         return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0199 
0200     } else {
0201 
0202         /* C14-13:1 */
0203         if (hop_cnt && *hop_ptr == hop_cnt + 1) {
0204             (*hop_ptr)--;
0205             return (return_path[*hop_ptr] ==
0206                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0207         }
0208 
0209         /* C14-13:2 */
0210         if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
0211             if (!is_switch)
0212                 return IB_SMI_DISCARD;
0213 
0214             /* hop_ptr updated when sending */
0215             return (return_path[*hop_ptr-1] <= phys_port_cnt ?
0216                 IB_SMI_HANDLE : IB_SMI_DISCARD);
0217         }
0218 
0219         /* C14-13:3 -- We're at the end of the DR segment of path */
0220         if (*hop_ptr == 1) {
0221             if (dr_slid_is_permissive) {
0222                 /* giving SMP to SM - update hop_ptr */
0223                 (*hop_ptr)--;
0224                 return IB_SMI_HANDLE;
0225             }
0226             /* hop_ptr updated when sending */
0227             return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0228         }
0229 
0230         /* C14-13:4 -- hop_ptr = 0 -> give to SM */
0231         /* C14-13:5 -- Check for unreasonable hop pointer */
0232         return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0233     }
0234 }
0235 
0236 /*
0237  * Adjust information for a received SMP
0238  * Return IB_SMI_DISCARD if the SMP should be dropped
0239  */
0240 enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch,
0241                        u32 port_num, int phys_port_cnt)
0242 {
0243     return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
0244                     &smp->hop_ptr, smp->hop_cnt,
0245                     smp->initial_path,
0246                     smp->return_path,
0247                     ib_get_smp_direction(smp),
0248                     smp->dr_dlid == IB_LID_PERMISSIVE,
0249                     smp->dr_slid == IB_LID_PERMISSIVE);
0250 }
0251 
0252 /*
0253  * Adjust information for a received SMP
0254  * Return IB_SMI_DISCARD if the SMP should be dropped
0255  */
0256 enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch,
0257                        u32 port_num, int phys_port_cnt)
0258 {
0259     return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
0260                     &smp->hop_ptr, smp->hop_cnt,
0261                     smp->route.dr.initial_path,
0262                     smp->route.dr.return_path,
0263                     opa_get_smp_direction(smp),
0264                     smp->route.dr.dr_dlid ==
0265                     OPA_LID_PERMISSIVE,
0266                     smp->route.dr.dr_slid ==
0267                     OPA_LID_PERMISSIVE);
0268 }
0269 
0270 static enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt,
0271                               u8 direction,
0272                               bool dr_dlid_is_permissive,
0273                               bool dr_slid_is_permissive)
0274 {
0275     if (!direction) {
0276         /* C14-9:2 -- intermediate hop */
0277         if (hop_ptr && hop_ptr < hop_cnt)
0278             return IB_SMI_FORWARD;
0279 
0280         /* C14-9:3 -- at the end of the DR segment of path */
0281         if (hop_ptr == hop_cnt)
0282             return (dr_dlid_is_permissive ?
0283                 IB_SMI_SEND : IB_SMI_LOCAL);
0284 
0285         /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
0286         if (hop_ptr == hop_cnt + 1)
0287             return IB_SMI_SEND;
0288     } else {
0289         /* C14-13:2  -- intermediate hop */
0290         if (2 <= hop_ptr && hop_ptr <= hop_cnt)
0291             return IB_SMI_FORWARD;
0292 
0293         /* C14-13:3 -- at the end of the DR segment of path */
0294         if (hop_ptr == 1)
0295             return (!dr_slid_is_permissive ?
0296                 IB_SMI_SEND : IB_SMI_LOCAL);
0297     }
0298     return IB_SMI_LOCAL;
0299 
0300 }
0301 
0302 enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
0303 {
0304     return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
0305                       ib_get_smp_direction(smp),
0306                       smp->dr_dlid == IB_LID_PERMISSIVE,
0307                       smp->dr_slid == IB_LID_PERMISSIVE);
0308 }
0309 
0310 enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp)
0311 {
0312     return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
0313                       opa_get_smp_direction(smp),
0314                       smp->route.dr.dr_dlid ==
0315                       OPA_LID_PERMISSIVE,
0316                       smp->route.dr.dr_slid ==
0317                       OPA_LID_PERMISSIVE);
0318 }
0319 
0320 /*
0321  * Return the forwarding port number from initial_path for outgoing SMP and
0322  * from return_path for returning SMP
0323  */
0324 int smi_get_fwd_port(struct ib_smp *smp)
0325 {
0326     return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
0327         smp->return_path[smp->hop_ptr-1]);
0328 }
0329 
0330 /*
0331  * Return the forwarding port number from initial_path for outgoing SMP and
0332  * from return_path for returning SMP
0333  */
0334 int opa_smi_get_fwd_port(struct opa_smp *smp)
0335 {
0336     return !opa_get_smp_direction(smp) ? smp->route.dr.initial_path[smp->hop_ptr+1] :
0337         smp->route.dr.return_path[smp->hop_ptr-1];
0338 }