The SCTP notification are alerts to peer clients and while the peer clients received the notification packets,peer client SCTP layer will genereate events to upper layer with ULP.
The notifications(SCTP to ULP) include below :
1. DATA ARRIVE notification
2. SEND FAILURE notification
3. NETWORK STATUS CHANGE notification
4. COMMNUICATION UP notification
5. COMMUNICATION LOST notification
6. COMMUNICATION ERROR notification
7. RESTART notification
8. SHUTDOWN COMPLETE notification
I traced source code from linux kernel 2.6.x . You can find the functions like sctp_ulpevent_type_enabled() from ulpevent.h,and follow after it is sctp_ulpq_tail_event() function to transmit.
Linux/net/sctp/chunk.c
----------------------
75 /* Final destructruction of datamsg memory. */
76 static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
77 {
78 struct list_head *pos, *temp;
79 struct sctp_chunk *chunk;
80 struct sctp_sock *sp;
81 struct sctp_ulpevent *ev;
82 struct sctp_association *asoc = NULL;
83 int error = 0, notify;
84
85 /* If we failed, we may need to notify. */
86 notify = msg->send_failed ? -1 : 0;
87
88 /* Release all references. */
89 list_for_each_safe(pos, temp, &msg->chunks) {
90 list_del_init(pos);
91 chunk = list_entry(pos, struct sctp_chunk, frag_list);
92 /* Check whether we _really_ need to notify. */
93 if (notify
94 asoc =chunk->asoc;
95 if (msg->send_error)
96 error = msg->send_error;
97 else
98 error = asoc->outqueue.error;
99
100 sp = sctp_sk(asoc->base.sk);
101 notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED,
102 &sp->subscribe);
103 }
104
105 /* Generate a SEND FAILED event only if enabled. */
106 if (notify > 0) {
107 int sent;
108 if (chunk->has_tsn)
109 sent = SCTP_DATA_SENT;
110 else
111 sent = SCTP_DATA_UNSENT;
112
113 ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent,
114 error, GFP_ATOMIC);
115 if (ev)
116 sctp_ulpq_tail_event(&asoc->ulpq, ev);
117 }
118
119 sctp_chunk_put(chunk);
120 }
121
122 SCTP_DBG_OBJCNT_DEC(datamsg);
123 kfree(msg);
124 }
In the line 200 of the ulpqueue.c , and the event will tail to SCTP queue list.
linux/net/sctp/ulpqueue.c
163 int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
164 {
165 struct sock *sk = ulpq->asoc->base.sk;
166 struct sk_buff_head *queue;
167 int clear_pd = 0;
168
169 /* If the socket is just going to throw this away, do not
170 * even try to deliver it.
171 */
172 if (sock_flag(sk, SOCK_DEAD) || (sk->sk_shutdown & RCV_SHUTDOWN))
173 goto out_free;
174
175 /* Check if the user wishes to receive this event. */
176 if (!sctp_ulpevent_is_enabled(event, &sctp_sk(sk)->subscribe))
177 goto out_free;
178
179 /* If we are in partial delivery mode, post to the lobby until
180 * partial delivery is cleared, unless, of course _this_ is
181 * the association the cause of the partial delivery.
182 */
183
184 if (!sctp_sk(sk)->pd_mode) {
185 queue = &sk->sk_receive_queue;
186 } else if (ulpq->pd_mode) {
187 if (event->msg_flags & MSG_NOTIFICATION)
188 queue = &sctp_sk(sk)->pd_lobby;
189 else {
190 clear_pd = event->msg_flags & MSG_EOR;
191 queue = &sk->sk_receive_queue;
192 }
193 } else
194 queue = &sctp_sk(sk)->pd_lobby;
195
196
197 /* If we are harvesting multiple skbs they will be
198 * collected on a list.
199 */
200 if (sctp_event2skb(event)->list)
201 sctp_skb_list_tail(sctp_event2skb(event)->list, queue);
202 else
203 __skb_queue_tail(queue, sctp_event2skb(event));
204
205 /* Did we just complete partial delivery and need to get
206 * rolling again? Move pending data to the receive
207 * queue.
208 */
209 if (clear_pd)
210 sctp_ulpq_clear_pd(ulpq);
211
212 if (queue == &sk->sk_receive_queue)
213 sk->sk_data_ready(sk, 0);
214 return 1;
215
216 out_free:
217 if (sctp_event2skb(event)->list)
218 sctp_queue_purge_ulpevents(sctp_event2skb(event)->list);
219 else
220 sctp_ulpevent_free(event);
221 return 0;
222 }
To be continue...