#! /bin/bash # # Copyright (c) 2017 Mellanox Technologies. All rights reserved. # # This Software is licensed under one of the following licenses: # # 1) under the terms of the "Common Public License 1.0" a copy of which is # available from the Open Source Initiative, see # http://www.opensource.org/licenses/cpl.php. # # 2) under the terms of the "The BSD License" a copy of which is # available from the Open Source Initiative, see # http://www.opensource.org/licenses/bsd-license.php. # # 3) under the terms of the "GNU General Public License (GPL) Version 2" a # copy of which is available from the Open Source Initiative, see # http://www.opensource.org/licenses/gpl-license.php. # # Licensee has the right to choose one of the above licenses. # # Redistributions of source code must retain the above copyright # notice and one of the license notices. # # Redistributions in binary form must reproduce both the above copyright # notice, one of the license notices in the documentation # and/or other materials provided with the distribution. # usage() { echo "$(basename $0) " echo "-h, --help print help message" echo "-v, --verbose print more info" } function find_pdev() { pdevlist=$(ls /sys/bus/pci/devices) for pdev in $pdevlist; do if [ -d /sys/bus/pci/devices/$pdev/infiniband ]; then ibd=$(ls /sys/bus/pci/devices/$pdev/infiniband/) if [ "x$ibd" == "x$1" ]; then echo -n $pdev fi fi done } case $1 in "-h" | "--help") usage exit 0 ;; esac if (( $# > 1 )); then usage exit -1 fi if (( $# == 1 )) && [ "$1" != "-v" ]; then usage exit -1 fi IP="ip" if [ -x /opt/mellanox/iproute2/sbin/ip ]; then IP="/opt/mellanox/iproute2/sbin/ip" fi if [ ! -d /sys/class/infiniband ]; then # driver is stopped exit -1 fi ibdevs=$(ls /sys/class/infiniband/) devs= for netpath in /sys/class/net/* do if (grep 0x15b3 ${netpath}/device/vendor > /dev/null 2>&1); then devs="$devs ${netpath##*/}" fi done if [ "x$devs" == "x" ]; then # no relevant devices - quit immediately exit fi for d in $devs; do if [ -f /sys/class/net/$d/dev_id ]; then oldstyle=n break fi done function print_verbose_info() { d=$1 port=$2 eth=$3 link_state=$4 filepath_portstate=/sys/class/infiniband/$d/ports/$port/state filepath_deviceid=/sys/class/infiniband/$d/device/device filepath_fwver=/sys/class/infiniband/$d/fw_ver filepath_vpd=/sys/class/infiniband/$d/device/vpd # read port state if [ -f $filepath_portstate ]; then ibstate=$(printf "%-6s" $(cat $filepath_portstate | awk '{print $2}')) else ibstate="NA" fi # read device if [ -f $filepath_deviceid ]; then devid=$(printf "MT%d" $(cat $filepath_deviceid)) else devid="NA" fi # read FW version if [ -f $filepath_fwver ]; then fwver=$(cat $filepath_fwver) else fwver="NA" fi # read device description and part ID from the VPD if [ -f $filepath_vpd ]; then tmp=$IFS IFS=":" vpd_content=`cat $filepath_vpd | strings` devdesc=$(printf "%-15s" $(echo $vpd_content | strings | head -1)) partid=$(printf "%-11s" $(echo $vpd_content | strings | head -4 | tail -1 | awk '{print $1}')) IFS=$tmp else devdesc="" partid="NA" fi x=$(find_pdev $d) echo "$x $d ($devid - $partid) $devdesc fw $fwver port $port ($ibstate) ==> $eth ($link_state)" } function get_link_state() { eth=$1 filepath_devid=/sys/class/net/$eth/dev_id if [ -f $filepath_devid ]; then filepath_carrier=/sys/class/net/$eth/carrier if [ -f $filepath_carrier ]; then link_state=$(cat $filepath_carrier 2> /dev/null) if (( link_state == 1 )); then link_state="Up" else link_state="Down" fi else link_state="NA" fi fi echo -n $link_state } function find_matching_ndev_for_gid() { gid=$1 gid_without_prefix=${gid#"fe80:0000:0000:0000:"} gid_without_colon=${gid_without_prefix//:} ip_link_output=$($IP link show) IFS=$'\n' read -rd '' -a array <<<"$ip_link_output" for index in "${!array[@]}" do #search for infiniband address if [[ ${array[index]} =~ .*infiniband.* ]]; then # skip bonding master interfaces if [[ ${array[index-1]} =~ .*MASTER.* ]]; then continue fi ib_addr=${array[index]} #retain string after link/infiniband ib_addr=${ib_addr##*infiniband} #retain string before brd ib_addr=${ib_addr%brd*} #extract 8 bytes of hw address ib_addr=${ib_addr:37:25} #remove : from the address, have only alphanumeric ib_addr=${ib_addr//:} ib_ndev_name=${array[index-1]} #retain string before : ib_ndev_name=${ib_ndev_name%:*} #retain string after : ib_ndev_name=${ib_ndev_name#*:} if [ $gid_without_colon == $ib_addr ]; then # skip zero (i.e., undefined) gids if [ "x$gid_without_colon" == "x0000000000000000" ]; then continue fi echo -n $ib_ndev_name break fi fi done } if [ "x$oldstyle" == "xn" ]; then for d in $ibdevs; do ports=$(ls /sys/class/infiniband/$d/ports/) for port in $ports; do link_layer=$(cat /sys/class/infiniband/$d/ports/$port/link_layer) if [ "x$link_layer" == "xInfiniBand" ]; then gid=$(cat /sys/class/infiniband/$d/ports/$port/gids/0) ethdev=$(find_matching_ndev_for_gid $gid) else ethdev=$(cat /sys/class/infiniband/$d/ports/$port/gid_attrs/ndevs/0 2> /dev/null) #Honor ndev given by the kernel in the gid table for RoCE, soft RoCE #if kernel doesn't expose it (for IB), try the different method of #resource match. fi if [[ -z $ethdev ]]; then ibrsc=$(cat /sys/class/infiniband/$d/device/resource) eths=$(ls /sys/class/net/) for eth in $eths; do filepath_resource=/sys/class/net/$eth/device/resource if [ -f $filepath_resource ]; then ethrsc=$(cat $filepath_resource) if [ "x$ethrsc" == "x$ibrsc" ]; then link_state=$(get_link_state $eth) x=$(find_pdev $d) if [ "$1" == "-v" ]; then print_verbose_info $d $port $eth $link_state else echo "$d port $port ==> $eth ($link_state)" fi break fi fi done else link_state=$(get_link_state $ethdev) if [ "$1" == "-v" ]; then print_verbose_info $d $port $ethdev $link_state else echo "$d port $port ==> $ethdev ($link_state)" fi fi done done else ########################## ### old style ########################## function print_line() { echo "$1 port $2 <===> $3" } function find_guid() { ibdevs=$(ls /sys/class/infiniband/) for ibdev in $ibdevs; do ports=$(ls /sys/class/infiniband/$ibdev/ports/) for port in $ports; do gids=$(ls /sys/class/infiniband/$ibdev/ports/$port/gids) for gid in $gids; do pguid=$(cat /sys/class/infiniband/$ibdev/ports/$port/gids/$gid | cut -b 21- | sed -e 's/://g') if [ x$pguid == x$1 ]; then print_line $ibdev $port $2 fi done done done } function find_mac() { ibdevs=$(ls /sys/class/infiniband/) for ibdev in $ibdevs; do ports=$(ls /sys/class/infiniband/$ibdev/ports/) for port in $ports; do gids=$(ls /sys/class/infiniband/$ibdev/ports/$port/gids) for gid in $gids; do first=$(cat /sys/class/infiniband/$ibdev/ports/$port/gids/$gid | cut -b 21-22) first=$(( first ^ 2 )) first=$(printf "%02x" $first) second=$(cat /sys/class/infiniband/$ibdev/ports/$port/gids/$gid | cut -b 21- | sed -e 's/://g' | cut -b 3-6) third=$(cat /sys/class/infiniband/$ibdev/ports/$port/gids/$gid | cut -b 21- | sed -e 's/://g' | cut -b 11-) pmac=$first$second$third if [ x$pmac == x$1 ]; then print_line $ibdev $port $2 fi done done done } ifcs=$($IP link | egrep '^[0-9]+: (ib|eth)' | awk '{print $2}' | tr -d :) for ifc in $ifcs; do len=$(cat /sys/class/net/$ifc/addr_len) if (( len == 20 )); then guid=$(cat /sys/class/net/$ifc/address | cut -b 37- | sed -e 's/://g') find_guid $guid $ifc elif (( len == 6)); then mac=$(cat /sys/class/net/$ifc/address | sed -e 's/://g') find_mac $mac $ifc fi done fi