tipc: narrow down interface towards struct tipc_link
[cascardo/linux.git] / net / tipc / link.c
index c513a80..4380eb1 100644 (file)
 
 #include <linux/pkt_sched.h>
 
+struct tipc_stats {
+       u32 sent_info;          /* used in counting # sent packets */
+       u32 recv_info;          /* used in counting # recv'd packets */
+       u32 sent_states;
+       u32 recv_states;
+       u32 sent_probes;
+       u32 recv_probes;
+       u32 sent_nacks;
+       u32 recv_nacks;
+       u32 sent_acks;
+       u32 sent_bundled;
+       u32 sent_bundles;
+       u32 recv_bundled;
+       u32 recv_bundles;
+       u32 retransmitted;
+       u32 sent_fragmented;
+       u32 sent_fragments;
+       u32 recv_fragmented;
+       u32 recv_fragments;
+       u32 link_congs;         /* # port sends blocked by congestion */
+       u32 deferred_recv;
+       u32 duplicates;
+       u32 max_queue_sz;       /* send queue size high water mark */
+       u32 accu_queue_sz;      /* used for send queue size profiling */
+       u32 queue_sz_counts;    /* used for send queue size profiling */
+       u32 msg_length_counts;  /* used for message length profiling */
+       u32 msg_lengths_total;  /* used for message length profiling */
+       u32 msg_length_profile[7]; /* used for msg. length profiling */
+};
+
+/**
+ * struct tipc_link - TIPC link data structure
+ * @addr: network address of link's peer node
+ * @name: link name character string
+ * @media_addr: media address to use when sending messages over link
+ * @timer: link timer
+ * @net: pointer to namespace struct
+ * @refcnt: reference counter for permanent references (owner node & timer)
+ * @peer_session: link session # being used by peer end of link
+ * @peer_bearer_id: bearer id used by link's peer endpoint
+ * @bearer_id: local bearer id used by link
+ * @tolerance: minimum link continuity loss needed to reset link [in ms]
+ * @keepalive_intv: link keepalive timer interval
+ * @abort_limit: # of unacknowledged continuity probes needed to reset link
+ * @state: current state of link FSM
+ * @peer_caps: bitmap describing capabilities of peer node
+ * @silent_intv_cnt: # of timer intervals without any reception from peer
+ * @proto_msg: template for control messages generated by link
+ * @pmsg: convenience pointer to "proto_msg" field
+ * @priority: current link priority
+ * @net_plane: current link network plane ('A' through 'H')
+ * @backlog_limit: backlog queue congestion thresholds (indexed by importance)
+ * @exp_msg_count: # of tunnelled messages expected during link changeover
+ * @reset_rcv_checkpt: seq # of last acknowledged message at time of link reset
+ * @mtu: current maximum packet size for this link
+ * @advertised_mtu: advertised own mtu when link is being established
+ * @transmitq: queue for sent, non-acked messages
+ * @backlogq: queue for messages waiting to be sent
+ * @snt_nxt: next sequence number to use for outbound messages
+ * @last_retransmitted: sequence number of most recently retransmitted message
+ * @stale_count: # of identical retransmit requests made by peer
+ * @ackers: # of peers that needs to ack each packet before it can be released
+ * @acked: # last packet acked by a certain peer. Used for broadcast.
+ * @rcv_nxt: next sequence number to expect for inbound messages
+ * @deferred_queue: deferred queue saved OOS b'cast message received from node
+ * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
+ * @inputq: buffer queue for messages to be delivered upwards
+ * @namedq: buffer queue for name table messages to be delivered upwards
+ * @next_out: ptr to first unsent outbound message in queue
+ * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate
+ * @long_msg_seq_no: next identifier to use for outbound fragmented messages
+ * @reasm_buf: head of partially reassembled inbound message fragments
+ * @bc_rcvr: marks that this is a broadcast receiver link
+ * @stats: collects statistics regarding link activity
+ */
+struct tipc_link {
+       u32 addr;
+       char name[TIPC_MAX_LINK_NAME];
+       struct tipc_media_addr *media_addr;
+       struct net *net;
+
+       /* Management and link supervision data */
+       u32 peer_session;
+       u32 peer_bearer_id;
+       u32 bearer_id;
+       u32 tolerance;
+       unsigned long keepalive_intv;
+       u32 abort_limit;
+       u32 state;
+       u16 peer_caps;
+       bool active;
+       u32 silent_intv_cnt;
+       struct {
+               unchar hdr[INT_H_SIZE];
+               unchar body[TIPC_MAX_IF_NAME];
+       } proto_msg;
+       struct tipc_msg *pmsg;
+       u32 priority;
+       char net_plane;
+
+       /* Failover/synch */
+       u16 drop_point;
+       struct sk_buff *failover_reasm_skb;
+
+       /* Max packet negotiation */
+       u16 mtu;
+       u16 advertised_mtu;
+
+       /* Sending */
+       struct sk_buff_head transmq;
+       struct sk_buff_head backlogq;
+       struct {
+               u16 len;
+               u16 limit;
+       } backlog[5];
+       u16 snd_nxt;
+       u16 last_retransm;
+       u16 window;
+       u32 stale_count;
+
+       /* Reception */
+       u16 rcv_nxt;
+       u32 rcv_unacked;
+       struct sk_buff_head deferdq;
+       struct sk_buff_head *inputq;
+       struct sk_buff_head *namedq;
+
+       /* Congestion handling */
+       struct sk_buff_head wakeupq;
+
+       /* Fragmentation/reassembly */
+       struct sk_buff *reasm_buf;
+
+       /* Broadcast */
+       u16 ackers;
+       u16 acked;
+       struct tipc_link *bc_rcvlink;
+       struct tipc_link *bc_sndlink;
+       int nack_state;
+       bool bc_peer_is_up;
+
+       /* Statistics */
+       struct tipc_stats stats;
+};
+
 /*
  * Error message prefixes
  */
@@ -165,6 +310,36 @@ void tipc_link_set_active(struct tipc_link *l, bool active)
        l->active = active;
 }
 
+u32 tipc_link_id(struct tipc_link *l)
+{
+       return l->peer_bearer_id << 16 | l->bearer_id;
+}
+
+int tipc_link_window(struct tipc_link *l)
+{
+       return l->window;
+}
+
+int tipc_link_prio(struct tipc_link *l)
+{
+       return l->priority;
+}
+
+unsigned long tipc_link_tolerance(struct tipc_link *l)
+{
+       return l->tolerance;
+}
+
+struct sk_buff_head *tipc_link_inputq(struct tipc_link *l)
+{
+       return l->inputq;
+}
+
+char tipc_link_plane(struct tipc_link *l)
+{
+       return l->net_plane;
+}
+
 void tipc_link_add_bc_peer(struct tipc_link *snd_l,
                           struct tipc_link *uc_l,
                           struct sk_buff_head *xmitq)
@@ -207,11 +382,31 @@ int tipc_link_mtu(struct tipc_link *l)
        return l->mtu;
 }
 
+u16 tipc_link_rcv_nxt(struct tipc_link *l)
+{
+       return l->rcv_nxt;
+}
+
+u16 tipc_link_acked(struct tipc_link *l)
+{
+       return l->acked;
+}
+
+char *tipc_link_name(struct tipc_link *l)
+{
+       return l->name;
+}
+
 static u32 link_own_addr(struct tipc_link *l)
 {
        return msg_prevnode(l->pmsg);
 }
 
+void tipc_link_reinit(struct tipc_link *l, u32 addr)
+{
+       msg_set_prevnode(l->pmsg, addr);
+}
+
 /**
  * tipc_link_create - create a new link
  * @n: pointer to associated node
@@ -674,7 +869,7 @@ void tipc_link_reset(struct tipc_link *l)
        l->stats.recv_info = 0;
        l->stale_count = 0;
        l->bc_peer_is_up = false;
-       link_reset_statistics(l);
+       tipc_link_reset_stats(l);
 }
 
 /**
@@ -1067,8 +1262,9 @@ drop:
 /*
  * Send protocol message to the other endpoint.
  */
-void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, int probe_msg,
-                         u32 gap, u32 tolerance, u32 priority)
+static void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ,
+                                int probe_msg, u32 gap, u32 tolerance,
+                                u32 priority)
 {
        struct sk_buff *skb = NULL;
        struct sk_buff_head xmitq;
@@ -1510,14 +1706,16 @@ void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
 }
 
 /**
- * link_reset_statistics - reset link statistics
+ * link_reset_stats - reset link statistics
  * @l_ptr: pointer to link
  */
-void link_reset_statistics(struct tipc_link *l_ptr)
+void tipc_link_reset_stats(struct tipc_link *l)
 {
-       memset(&l_ptr->stats, 0, sizeof(l_ptr->stats));
-       l_ptr->stats.sent_info = l_ptr->snd_nxt;
-       l_ptr->stats.recv_info = l_ptr->rcv_nxt;
+       memset(&l->stats, 0, sizeof(l->stats));
+       if (!link_is_bc_sndlink(l)) {
+               l->stats.sent_info = l->snd_nxt;
+               l->stats.recv_info = l->rcv_nxt;
+       }
 }
 
 static void link_print(struct tipc_link *l, const char *str)
@@ -1705,3 +1903,135 @@ msg_full:
 
        return -EMSGSIZE;
 }
+
+static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb,
+                                     struct tipc_stats *stats)
+{
+       int i;
+       struct nlattr *nest;
+
+       struct nla_map {
+               __u32 key;
+               __u32 val;
+       };
+
+       struct nla_map map[] = {
+               {TIPC_NLA_STATS_RX_INFO, stats->recv_info},
+               {TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments},
+               {TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented},
+               {TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles},
+               {TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled},
+               {TIPC_NLA_STATS_TX_INFO, stats->sent_info},
+               {TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments},
+               {TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented},
+               {TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles},
+               {TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled},
+               {TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks},
+               {TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv},
+               {TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks},
+               {TIPC_NLA_STATS_TX_ACKS, stats->sent_acks},
+               {TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted},
+               {TIPC_NLA_STATS_DUPLICATES, stats->duplicates},
+               {TIPC_NLA_STATS_LINK_CONGS, stats->link_congs},
+               {TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz},
+               {TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ?
+                       (stats->accu_queue_sz / stats->queue_sz_counts) : 0}
+       };
+
+       nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
+       if (!nest)
+               return -EMSGSIZE;
+
+       for (i = 0; i <  ARRAY_SIZE(map); i++)
+               if (nla_put_u32(skb, map[i].key, map[i].val))
+                       goto msg_full;
+
+       nla_nest_end(skb, nest);
+
+       return 0;
+msg_full:
+       nla_nest_cancel(skb, nest);
+
+       return -EMSGSIZE;
+}
+
+int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
+{
+       int err;
+       void *hdr;
+       struct nlattr *attrs;
+       struct nlattr *prop;
+       struct tipc_net *tn = net_generic(net, tipc_net_id);
+       struct tipc_link *bcl = tn->bcl;
+
+       if (!bcl)
+               return 0;
+
+       tipc_bcast_lock(net);
+
+       hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+                         NLM_F_MULTI, TIPC_NL_LINK_GET);
+       if (!hdr)
+               return -EMSGSIZE;
+
+       attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
+       if (!attrs)
+               goto msg_full;
+
+       /* The broadcast link is always up */
+       if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
+               goto attr_msg_full;
+
+       if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST))
+               goto attr_msg_full;
+       if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
+               goto attr_msg_full;
+       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt))
+               goto attr_msg_full;
+       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt))
+               goto attr_msg_full;
+
+       prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
+       if (!prop)
+               goto attr_msg_full;
+       if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window))
+               goto prop_msg_full;
+       nla_nest_end(msg->skb, prop);
+
+       err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats);
+       if (err)
+               goto attr_msg_full;
+
+       tipc_bcast_unlock(net);
+       nla_nest_end(msg->skb, attrs);
+       genlmsg_end(msg->skb, hdr);
+
+       return 0;
+
+prop_msg_full:
+       nla_nest_cancel(msg->skb, prop);
+attr_msg_full:
+       nla_nest_cancel(msg->skb, attrs);
+msg_full:
+       tipc_bcast_unlock(net);
+       genlmsg_cancel(msg->skb, hdr);
+
+       return -EMSGSIZE;
+}
+
+void tipc_link_set_tolerance(struct tipc_link *l, u32 tol)
+{
+       l->tolerance = tol;
+       tipc_link_proto_xmit(l, STATE_MSG, 0, 0, tol, 0);
+}
+
+void tipc_link_set_prio(struct tipc_link *l, u32 prio)
+{
+       l->priority = prio;
+       tipc_link_proto_xmit(l, STATE_MSG, 0, 0, 0, prio);
+}
+
+void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit)
+{
+       l->abort_limit = limit;
+}