Motr  M0
protection_info_checks.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2021 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 #ifndef __KERNEL__
23 #include <openssl/md5.h>
24 #endif /* __KERNEL__ */
25 
26 #include "ut/ut.h"
27 #include "motr/client.h"
28 #include "motr/client_internal.h"
29 #include "motr/ut/client.h"
30 #include "lib/cksum.h"
31 
32 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CLIENT
33 #include "lib/trace.h" /* M0_LOG */
34 
36 
37 enum {
38  BUFFER_SIZE = 4096,
39  SEGS_NR = 16,
40 
41  BIG_BUFFER_SIZE = 4096*16,
43 };
44 
45 #define DATA_UNIT_COUNT 10
46 #define OBJ_CONTAINER 0x123
47 #define OBJ_KEY 0x456
48 
50 unsigned char *curr_context[DATA_UNIT_COUNT];
51 unsigned char *seeded_sum[DATA_UNIT_COUNT];
52 unsigned char *final_sum;
53 
55 unsigned char *big_curr_context;
56 unsigned char *big_final_sum;
57 
58 M0_INTERNAL int pi_init(void)
59 {
60 #ifndef __KERNEL__
62 #endif
63 
64  int i, j, rc;
65  // allocate and populate buffers
66 
69 
70  for (j = 0; j < DATA_UNIT_COUNT; j++) {
72  M0_UT_ASSERT(rc == 0);
73  for (i = 0; i < user_data[j].ov_vec.v_nr; ++i) {
74  memset(user_data[j].ov_buf[i], 'a' + j, BUFFER_SIZE);
75  }
76 
77  M0_ALLOC_ARR(curr_context[j], sizeof(MD5_CTX));
79  M0_ALLOC_ARR(seeded_sum[j], MD5_DIGEST_LENGTH);
81  }
82 
83  M0_ALLOC_ARR(final_sum, MD5_DIGEST_LENGTH);
85 
89  M0_UT_ASSERT(rc == 0);
90  for (i = 0; i < big_user_data->ov_vec.v_nr; ++i) {
91  memset(big_user_data->ov_buf[i], 'a' + i, BIG_BUFFER_SIZE);
92  }
93 
94  M0_ALLOC_ARR(big_curr_context, sizeof(MD5_CTX));
96 
97  M0_ALLOC_ARR(big_final_sum, MD5_DIGEST_LENGTH);
99 
100  return 0;
101 }
102 
103 M0_INTERNAL int pi_fini(void)
104 {
105  int j;
106 
107  for (j = 0; j < DATA_UNIT_COUNT; j++) {
109  m0_free(seeded_sum[j]);
110  m0_free(curr_context[j]);
111  }
112 
119  return 0;
120 }
121 
123 {
124  int i, j, rc;
125  MD5_CTX curr_ctx;
126  MD5_CTX tmp_ctx;
127  char seed_str[64] = {'\0'};
128  struct m0_pi_seed seed;
129  unsigned char *seed_sum;
130  unsigned char *unseed_final_sum;
131 
132  M0_ALLOC_ARR(seed_sum, MD5_DIGEST_LENGTH);
133  M0_UT_ASSERT(seed_sum != NULL);
134  M0_ALLOC_ARR(unseed_final_sum, MD5_DIGEST_LENGTH);
135  M0_UT_ASSERT(unseed_final_sum != NULL);
136 
137  rc = MD5_Init(&curr_ctx);
138  M0_UT_ASSERT(rc == 1);
139 
140  for (j = 0; j < DATA_UNIT_COUNT; j++)
141  {
142  for (i = 0; i < user_data[j].ov_vec.v_nr; i++) {
143  rc = MD5_Update(&curr_ctx, user_data[j].ov_buf[i],
144  user_data[j].ov_vec.v_count[i]);
145  M0_UT_ASSERT(rc == 1);
146  }
147 
148  M0_UT_ASSERT(memcmp((MD5_CTX *)curr_context[j], &curr_ctx,
149  sizeof(MD5_CTX)) == 0);
150 
151  if (j == DATA_UNIT_COUNT - 1 ) {
152  rc = MD5_Final(unseed_final_sum, &curr_ctx);
153  M0_UT_ASSERT(rc == 1);
154  M0_UT_ASSERT(memcmp(final_sum, unseed_final_sum,
155  MD5_DIGEST_LENGTH) == 0);
156  }
157  }
158 
159  m0_fid_set(&seed.pis_obj_id, OBJ_CONTAINER, OBJ_KEY);
160  for (j = 0; j < DATA_UNIT_COUNT; j++)
161  {
162  memcpy((void *)&tmp_ctx,(void *)curr_context[j],sizeof(MD5_CTX));
163  seed.pis_data_unit_offset = j*SEGS_NR*BUFFER_SIZE;
164  snprintf(seed_str,sizeof(seed_str),"%" PRIx64 "%" PRIx64 "%"PRIx64,
165  seed.pis_obj_id.f_container, seed.pis_obj_id.f_key,
166  seed.pis_data_unit_offset);
167 
168  rc = MD5_Update(&tmp_ctx, (unsigned char *)seed_str,
169  sizeof(seed_str));
170  M0_UT_ASSERT(rc == 1);
171  rc = MD5_Final(seed_sum, &tmp_ctx);
172  M0_UT_ASSERT(rc == 1);
173  M0_UT_ASSERT(memcmp(seeded_sum[j], seed_sum,
174  MD5_DIGEST_LENGTH) == 0);
175  }
176 
178  MD5_DIGEST_LENGTH) == 0);
179 
180  m0_free(seed_sum);
181  m0_free(unseed_final_sum);
182 }
183 
184 /*
185  * CASE1:
186  * Calculate seeded checksums and non seeded contexts via API
187  * for multilple data units one by one. Calculate unseeded checksum
188  * for last data unit.
189  * Verification : Calculate seeded checksums and non seeded contexts
190  * via UT code verify_case_one_two() for multilple data units one by one.
191  * Calculate unseeded checksum for last data unit.
192  * Compare seeded checksums and non seeded contexts and final unseeded
193  * checksum obtained via API and UT. API and UT calculations should match.
194  *
195  * CASE2:
196  * step 1: Pass all the data units as one chunk to API with no seed and compute
197  * unseeded final checksum.
198  * step 2: Calculate seeded checksums and non seeded contexts via API
199  * for multilple data units one by one. Calculate unseeded checksum
200  * for last data unit. (Already done by case 1)
201  * Verification : Unseeded checksum from step1 and step2 should match.
202  */
204 {
205 
206  int j, rc;
207  struct m0_md5_inc_context_pi pi;
208  struct m0_pi_seed seed;
209 
210  m0_fid_set(&seed.pis_obj_id, OBJ_CONTAINER, OBJ_KEY);
211 
212  memset(&pi, 0, sizeof(struct m0_md5_inc_context_pi));
213  pi.pimd5c_hdr.pih_type = M0_PI_TYPE_MD5_INC_CONTEXT;
214 
215  for (j = 0; j < DATA_UNIT_COUNT; j++) {
216 
217  seed.pis_data_unit_offset = j*SEGS_NR*BUFFER_SIZE;
218  if (j == 0) {
221  curr_context[j], NULL);
222  M0_UT_ASSERT(rc == 0);
223  }
224  else if (j == DATA_UNIT_COUNT - 1) {
227  curr_context[j], final_sum);
228  M0_UT_ASSERT(rc == 0);
229  }
230  else {
233  curr_context[j], NULL);
234  M0_UT_ASSERT(rc == 0);
235  }
236 
237  memcpy(pi.pimd5c_prev_context, curr_context[j], sizeof(MD5_CTX));
238  memcpy(seeded_sum[j], pi.pimd5c_value, MD5_DIGEST_LENGTH);
239  }
240 
241  memset(&pi, 0, sizeof(struct m0_md5_inc_context_pi));
242  pi.pimd5c_hdr.pih_type = M0_PI_TYPE_MD5_INC_CONTEXT;
246  M0_UT_ASSERT(rc == 0);
247 
249 }
250 
251 
252 /* CASE 3:
253  * STEP1: Call API for different data units one by one. Seed should be passed
254  * for only last data unit which is some non-zero offset.
255  * STEP2 : call API one time with all data units as one chunk
256  * with the same seed as used in step1.
257  * Verification: seeded checksum (pi_value) from both the steps should match.
258  */
259 static void ut_test_pi_api_case_third(void)
260 {
261 
262  int j, rc;
263  struct m0_md5_inc_context_pi pi;
264  struct m0_pi_seed seed;
265  unsigned char seeded_final_chunks_value[MD5_DIGEST_LENGTH];
266 
267  m0_fid_set(&seed.pis_obj_id, OBJ_CONTAINER, OBJ_KEY);
268  seed.pis_data_unit_offset = (DATA_UNIT_COUNT-1)*SEGS_NR*BUFFER_SIZE;
269 
270  memset(&pi, 0, sizeof(struct m0_md5_inc_context_pi));
271  pi.pimd5c_hdr.pih_type = M0_PI_TYPE_MD5_INC_CONTEXT;
272 
273  /* STEP 1 */
274  for (j = 0; j < DATA_UNIT_COUNT; j++) {
275 
276  if (j == 0) {
279  curr_context[j], NULL);
280  M0_UT_ASSERT(rc == 0);
281  }
282  else if (j == DATA_UNIT_COUNT - 1) {
285  curr_context[j], final_sum);
286  M0_UT_ASSERT(rc == 0);
287  }
288  else {
291  curr_context[j], NULL);
292  M0_UT_ASSERT(rc == 0);
293  }
294 
295  memcpy(pi.pimd5c_prev_context, curr_context[j], sizeof(MD5_CTX));
296  memcpy(seeded_sum[j], pi.pimd5c_value, MD5_DIGEST_LENGTH);
297  }
298 
299  memcpy(&seeded_final_chunks_value, pi.pimd5c_value, MD5_DIGEST_LENGTH);
300 
301  /* STEP 2 */
302  memset(&pi, 0, sizeof(struct m0_md5_inc_context_pi));
303  pi.pimd5c_hdr.pih_type = M0_PI_TYPE_MD5_INC_CONTEXT;
307  M0_UT_ASSERT(rc == 0);
308 
309  /* VERIFICATION */
310  M0_UT_ASSERT(memcmp(&seeded_final_chunks_value, pi.pimd5c_value,
311  MD5_DIGEST_LENGTH) == 0);
312  M0_UT_ASSERT(memcmp(final_sum, big_final_sum, MD5_DIGEST_LENGTH) == 0);
313 
314 }
315 
316 
317 struct m0_ut_suite ut_suite_pi = {
318  .ts_name = "pi_ut",
319  .ts_init = pi_init,
320  .ts_fini = pi_fini,
321  .ts_tests = {
322 
323  /* Initialising client. */
324  { "m0_pi_checks_case_one_two", &ut_test_pi_api_case_one_two},
325  { "m0_pi_checks_case_third", &ut_test_pi_api_case_third},
326  { NULL, NULL },
327  }
328 };
329 
330 #undef M0_TRACE_SUBSYSTEM
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
#define NULL
Definition: misc.h:38
M0_INTERNAL int pi_init(void)
unsigned char * curr_context[DATA_UNIT_COUNT]
static void ut_test_pi_api_case_one_two(void)
struct m0_bufvec * user_data
static void ut_test_pi_api_case_third(void)
int m0_client_calculate_pi(struct m0_generic_pi *pi, struct m0_pi_seed *seed, struct m0_bufvec *bvec, enum m0_pi_calc_flag flag, unsigned char *curr_context, unsigned char *pi_value_without_seed)
Definition: cksum.c:168
struct m0_vec ov_vec
Definition: vec.h:147
struct m0_ut_suite ut_suite_pi
M0_INTERNAL int pi_fini(void)
struct m0_bufvec * big_user_data
#define DATA_UNIT_COUNT
unsigned char * big_curr_context
Definition: ut.h:77
void ** ov_buf
Definition: vec.h:149
#define PRIx64
Definition: types.h:61
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
unsigned char * seeded_sum[DATA_UNIT_COUNT]
int i
Definition: dir.c:1033
M0_INTERNAL void m0_fid_set(struct m0_fid *fid, uint64_t container, uint64_t key)
Definition: fid.c:116
unsigned char * big_final_sum
M0_INTERNAL void ut_shuffle_test_order(struct m0_ut_suite *suite)
Definition: client.c:1205
struct m0_pdclust_instance pi
Definition: fd.c:107
uint32_t v_nr
Definition: vec.h:51
const char * ts_name
Definition: ut.h:99
void verify_case_one_two(void)
unsigned char * final_sum
void m0_free(void *data)
Definition: memory.c:146
int32_t rc
Definition: trigger_fop.h:47
#define OBJ_CONTAINER
#define M0_UT_ASSERT(a)
Definition: ut.h:46
#define OBJ_KEY
Definition: vec.h:145